> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sendpost.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Flask Quickstart

> Learn how to send emails with SendPost in your Flask application using blueprints, utilities, and error handling

## Prerequisites

To get the most out of this guide, you'll need to:

* [**Create a SendPost Account**](https://app.sendpost.io/register)
* [**Flask 2.0+**](https://flask.palletsprojects.com/)
* [**Python 3.8+**](https://www.python.org/downloads/)
* A **Sub-Account API Key** from your SendPost dashboard

<Info>
  You can find your API keys in your [SendPost Dashboard](https://app.sendpost.io). Make sure to use your Sub-Account API Key for sending emails.
</Info>

## 1. Install Dependencies

```shellscript pip theme={null}
pip install flask sendpost-python-sdk python-dotenv
```

## 2. Environment Setup

Create a `.env` file:

```env theme={null}
SENDPOST_API_KEY=your_sub_account_api_key
SENDPOST_FROM_EMAIL=hello@playwithsendpost.io
SENDPOST_FROM_NAME=SendPost
FLASK_ENV=development
```

## 3. Basic Flask App Setup

Create `app.py`:

```python Python theme={null}
from flask import Flask
from dotenv import load_dotenv
import os

load_dotenv()

app = Flask(__name__)
app.config['SENDPOST_API_KEY'] = os.getenv('SENDPOST_API_KEY')
app.config['SENDPOST_FROM_EMAIL'] = os.getenv('SENDPOST_FROM_EMAIL')
app.config['SENDPOST_FROM_NAME'] = os.getenv('SENDPOST_FROM_NAME')

if __name__ == '__main__':
    app.run(debug=True)
```

## 4. Create Email Utility

Create `utils/email_service.py`:

```python Python theme={null}
import sendpost_python_sdk
from sendpost_python_sdk.api import EmailApi
from sendpost_python_sdk.models import EmailMessageObject, EmailAddress, Recipient
from flask import current_app
import re

class SendPostEmailService:
    @staticmethod
    def send_email(
        to,
        subject,
        html_body,
        text_body=None,
        from_email=None,
        from_name=None,
        groups=None,
        track_opens=True,
        track_clicks=True,
        custom_fields=None,
    ):
        """
        Send an email using SendPost API.
        
        Args:
            to: Email address (str) or list of Recipient objects/dicts
            subject: Email subject
            html_body: HTML email body
            text_body: Plain text email body (optional)
            from_email: Sender email (optional)
            from_name: Sender name (optional)
            groups: List of groups for email classification
            track_opens: Enable open tracking
            track_clicks: Enable click tracking
            custom_fields: Dict of custom fields for personalization
        
        Returns:
            dict: {'success': bool, 'message_id': str or None, 'error': str or None}
        """
        try:
            configuration = sendpost_python_sdk.Configuration(
                host="https://api.sendpost.io/api/v1"
            )
            configuration.api_key['subAccountAuth'] = current_app.config['SENDPOST_API_KEY']
            
            with sendpost_python_sdk.ApiClient(configuration) as api_client:
                email_message = EmailMessageObject()
                
                # Set sender
                email_message.var_from = EmailAddress(
                    email=from_email or current_app.config['SENDPOST_FROM_EMAIL'],
                    name=from_name or current_app.config['SENDPOST_FROM_NAME']
                )
                
                # Handle recipients
                if isinstance(to, str):
                    recipients = [Recipient(email=to)]
                elif isinstance(to, list):
                    recipients = []
                    for recipient in to:
                        if isinstance(recipient, str):
                            recipients.append(Recipient(email=recipient))
                        elif isinstance(recipient, dict):
                            recipients.append(Recipient(
                                email=recipient.get('email'),
                                name=recipient.get('name'),
                                custom_fields=recipient.get('customFields') or custom_fields
                            ))
                        else:
                            recipients.append(recipient)
                else:
                    recipients = [Recipient(email=to)]
                
                email_message.to = recipients
                email_message.subject = subject
                email_message.html_body = html_body
                email_message.text_body = text_body or SendPostEmailService._html_to_text(html_body)
                email_message.track_opens = track_opens
                email_message.track_clicks = track_clicks
                
                if groups:
                    email_message.groups = groups if isinstance(groups, list) else [groups]
                
                response = EmailApi(api_client).send_email(email_message)[0]
                
                return {
                    'success': True,
                    'message_id': response.message_id,
                    'data': response
                }
        except sendpost_python_sdk.exceptions.ApiException as e:
            current_app.logger.error(f"SendPost API error: {e.status} - {e.body}")
            return {
                'success': False,
                'message_id': None,
                'error': f"API Error {e.status}: {e.body}"
            }
        except Exception as e:
            current_app.logger.error(f"SendPost error: {str(e)}")
            return {
                'success': False,
                'message_id': None,
                'error': str(e)
            }
    
    @staticmethod
    def _html_to_text(html):
        """Simple HTML to text conversion"""
        text = re.sub(r'<[^>]+>', '', html)
        text = text.replace('&nbsp;', ' ')
        text = text.replace('&amp;', '&')
        text = text.replace('&lt;', '<')
        text = text.replace('&gt;', '>')
        return text.strip()
```

## 5. Send Your First Email

### Simple Route

```python Python theme={null}
from flask import Flask, request, jsonify
from utils.email_service import SendPostEmailService

app = Flask(__name__)

@app.route('/api/send-email', methods=['POST'])
def send_email():
    try:
        data = request.get_json()
        to = data.get('to')
        subject = data.get('subject')
        html_body = data.get('htmlBody')
        
        if not all([to, subject, html_body]):
            return jsonify({
                'success': False,
                'error': 'Missing required fields: to, subject, htmlBody'
            }), 400
        
        result = SendPostEmailService.send_email(
            to=to,
            subject=subject,
            html_body=html_body,
            text_body=data.get('textBody')
        )
        
        if result['success']:
            return jsonify({
                'success': True,
                'messageId': result['message_id']
            })
        else:
            return jsonify({
                'success': False,
                'error': result['error']
            }), 500
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500
```

## 6. Common Use Cases

### Welcome Email Route

```python Python theme={null}
@app.route('/api/welcome-email', methods=['POST'])
def send_welcome_email():
    try:
        data = request.get_json()
        email = data.get('email')
        first_name = data.get('firstName')
        
        if not email or not first_name:
            return jsonify({
                'success': False,
                'error': 'Missing required fields: email, firstName'
            }), 400
        
        result = SendPostEmailService.send_email(
            to={
                'email': email,
                'name': first_name,
                'customFields': {'firstName': first_name}
            },
            subject='Welcome {{firstName}}!',
            html_body='''
                <h1>Welcome, {{firstName}}!</h1>
                <p>Thank you for joining us. We're excited to have you on board.</p>
                <p>Get started by exploring our features:</p>
                <ul>
                    <li>Feature 1</li>
                    <li>Feature 2</li>
                    <li>Feature 3</li>
                </ul>
                <p>If you have any questions, just reply to this email.</p>
                <p><a href="{{unsubscribe}}">Unsubscribe</a></p>
            ''',
            text_body='''
                Welcome, {{firstName}}!
                
                Thank you for joining us. We're excited to have you on board.
                
                Get started by exploring our features:
                - Feature 1
                - Feature 2
                - Feature 3
                
                If you have any questions, just reply to this email.
                
                Unsubscribe: {{unsubscribe}}
            ''',
            groups=['welcome']
        )
        
        if result['success']:
            return jsonify({
                'success': True,
                'messageId': result['message_id']
            })
        else:
            return jsonify({
                'success': False,
                'error': result['error']
            }), 500
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500
```

### Password Reset Email

```python Python theme={null}
@app.route('/api/password-reset', methods=['POST'])
def send_password_reset():
    try:
        data = request.get_json()
        email = data.get('email')
        reset_token = data.get('resetToken')
        first_name = data.get('firstName', 'User')
        
        if not email or not reset_token:
            return jsonify({
                'success': False,
                'error': 'Missing required fields: email, resetToken'
            }), 400
        
        reset_url = f"{request.host_url}reset-password?token={reset_token}"
        
        result = SendPostEmailService.send_email(
            to={
                'email': email,
                'name': first_name,
                'customFields': {
                    'firstName': first_name,
                    'resetUrl': reset_url
                }
            },
            subject='Reset Your Password',
            html_body='''
                <h2>Hello {{firstName}},</h2>
                <p>We received a request to reset your password. Click the button below:</p>
                <p>
                    <a href="{{resetUrl}}" style="background-color: #5750EC; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; display: inline-block;">
                        Reset Password
                    </a>
                </p>
                <p>Or copy and paste this link: {{resetUrl}}</p>
                <p>This link will expire in 1 hour.</p>
                <p>If you didn't request this, please ignore this email.</p>
            ''',
            text_body='''
                Hello {{firstName}},
                
                We received a request to reset your password. Click the link below:
                
                {{resetUrl}}
                
                This link will expire in 1 hour.
                
                If you didn't request this, please ignore this email.
            ''',
            groups=['password-reset'],
            track_clicks=True
        )
        
        if result['success']:
            return jsonify({
                'success': True,
                'messageId': result['message_id']
            })
        else:
            return jsonify({
                'success': False,
                'error': result['error']
            }), 500
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500
```

## 7. Using Blueprints

Create `blueprints/email_bp.py`:

```python Python theme={null}
from flask import Blueprint, request, jsonify
from utils.email_service import SendPostEmailService

email_bp = Blueprint('email', __name__, url_prefix='/api/email')

@email_bp.route('/send', methods=['POST'])
def send_email():
    """Send a basic email"""
    try:
        data = request.get_json()
        to = data.get('to')
        subject = data.get('subject')
        html_body = data.get('htmlBody')
        
        if not all([to, subject, html_body]):
            return jsonify({
                'success': False,
                'error': 'Missing required fields: to, subject, htmlBody'
            }), 400
        
        result = SendPostEmailService.send_email(
            to=to,
            subject=subject,
            html_body=html_body,
            text_body=data.get('textBody')
        )
        
        if result['success']:
            return jsonify({
                'success': True,
                'messageId': result['message_id']
            })
        else:
            return jsonify({
                'success': False,
                'error': result['error']
            }), 500
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@email_bp.route('/welcome', methods=['POST'])
def welcome_email():
    """Send welcome email"""
    # ... implementation similar to above ...
    pass

@email_bp.route('/password-reset', methods=['POST'])
def password_reset_email():
    """Send password reset email"""
    # ... implementation similar to above ...
    pass
```

Register in `app.py`:

```python Python theme={null}
from blueprints.email_bp import email_bp

app.register_blueprint(email_bp)
```

## 8. Error Handling

Create `errors.py`:

```python Python theme={null}
from flask import jsonify
from werkzeug.exceptions import HTTPException

def register_error_handlers(app):
    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            'success': False,
            'error': 'Bad request',
            'message': str(error)
        }), 400
    
    @app.errorhandler(500)
    def internal_error(error):
        return jsonify({
            'success': False,
            'error': 'Internal server error',
            'message': str(error) if app.debug else 'An error occurred'
        }), 500
    
    @app.errorhandler(Exception)
    def handle_exception(e):
        if isinstance(e, HTTPException):
            return e
        
        app.logger.error(f"Unhandled exception: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Internal server error',
            'message': str(e) if app.debug else 'An error occurred'
        }), 500
```

Use in `app.py`:

```python Python theme={null}
from errors import register_error_handlers

register_error_handlers(app)
```

## 9. Using Flask-Mail Style Interface (Optional)

Create `extensions/email.py`:

```python Python theme={null}
from flask import current_app
from utils.email_service import SendPostEmailService

class Message:
    def __init__(self, subject, recipients, body, html=None, sender=None):
        self.subject = subject
        self.recipients = recipients if isinstance(recipients, list) else [recipients]
        self.body = body
        self.html = html
        self.sender = sender

class Mail:
    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)
    
    def init_app(self, app):
        self.app = app
    
    def send(self, message):
        """Send email message using SendPost"""
        html_body = message.html or message.body
        text_body = message.body if message.html else None
        
        result = SendPostEmailService.send_email(
            to=message.recipients,
            subject=message.subject,
            html_body=html_body,
            text_body=text_body,
            from_email=message.sender
        )
        
        if not result['success']:
            raise Exception(result['error'])
        
        return result
```

Use it:

```python Python theme={null}
from extensions.email import Mail, Message

mail = Mail()

@app.route('/send')
def send():
    msg = Message(
        subject='Hello',
        recipients=['user@example.com'],
        body='Plain text body',
        html='<h1>HTML body</h1>'
    )
    mail.send(msg)
    return 'Email sent!'
```

<Warning>
  Make sure your sender email domain is verified in your SendPost account before sending emails.
</Warning>

## 10. Next Steps

Explore more examples and use cases:

<Columns cols={3}>
  <Card title="Flask Documentation" icon="flask" href="https://flask.palletsprojects.com/">
    Learn more about Flask framework
  </Card>

  <Card title="SendPost Python SDK" icon="python" href="https://pypi.org/project/sendpost-python-sdk/">
    View the official SDK package on PyPI
  </Card>

  <Card title="Quickstart Example" icon="github" href="https://github.com/sendpost/sendpost-flask-example">
    View a complete working example on GitHub
  </Card>
</Columns>
