Usage ===== This guide covers the various ways to use django-forwardemail in your Django applications. Basic Email Sending -------------------- The simplest way to send emails is using the ``ForwardEmailService`` class (``EmailService`` is a backward-compatible alias): .. code-block:: python from django_forwardemail.services import ForwardEmailService # Send a basic email ForwardEmailService.send_email( to='user@example.com', subject='Welcome to our service!', text='Thank you for signing up. We are excited to have you on board.', ) HTML Email Support ------------------ You can send HTML emails by providing both text and HTML content: .. code-block:: python ForwardEmailService.send_email( to='user@example.com', subject='Welcome to our service!', text='Thank you for signing up. We are excited to have you on board.', html='''
Thank you for signing up. We are excited to have you on board.
''' ) Advanced Parameters ------------------- The ``send_email`` method supports several optional parameters: .. code-block:: python ForwardEmailService.send_email( to='user@example.com', subject='Custom Email', text='Email content', html='Email content
', from_email='custom@example.com', # Override default from email reply_to='support@example.com', # Set reply-to address request=request, # For site detection in views site=specific_site # Explicit site specification ) Using in Django Views --------------------- Here are common patterns for using django-forwardemail in Django views: Registration Confirmation ~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: python from django.shortcuts import render, redirect from django.contrib.auth import login from django.contrib import messages from django_forwardemail.services import ForwardEmailService def register_view(request): if request.method == 'POST': form = UserRegistrationForm(request.POST) if form.is_valid(): user = form.save() # Send welcome email try: ForwardEmailService.send_email( to=user.email, subject='Welcome to Example.com!', text=f'Hi {user.first_name}, welcome to our platform!', html=f'Welcome to our platform!
', request=request # Site detection from request ) messages.success(request, 'Registration successful! Check your email.') except Exception as e: messages.warning(request, 'Registration successful, but email could not be sent.') login(request, user) return redirect('dashboard') else: form = UserRegistrationForm() return render(request, 'registration/register.html', {'form': form}) Password Reset ~~~~~~~~~~~~~~ .. code-block:: python from django.contrib.auth.tokens import default_token_generator from django.utils.http import urlsafe_base64_encode from django.utils.encoding import force_bytes from django.urls import reverse def password_reset_view(request): if request.method == 'POST': email = request.POST.get('email') try: user = User.objects.get(email=email) # Generate reset token token = default_token_generator.make_token(user) uid = urlsafe_base64_encode(force_bytes(user.pk)) # Build reset URL reset_url = request.build_absolute_uri( reverse('password_reset_confirm', kwargs={'uidb64': uid, 'token': token}) ) # Send reset email ForwardEmailService.send_email( to=user.email, subject='Password Reset Request', text=f'Click the link to reset your password: {reset_url}', html=f'''Click the link below to reset your password:
If you didn't request this, please ignore this email.
''', request=request ) messages.success(request, 'Password reset email sent!') except User.DoesNotExist: messages.error(request, 'No user found with that email address.') return render(request, 'registration/password_reset.html') Using with Django Templates ---------------------------- You can render Django templates for email content: .. code-block:: python from django.template.loader import render_to_string from django.utils.html import strip_tags def send_notification_email(user, notification_data): # Render HTML template html_content = render_to_string('emails/notification.html', { 'user': user, 'notification': notification_data, 'site_url': 'https://example.com' }) # Create plain text version text_content = strip_tags(html_content) ForwardEmailService.send_email( to=user.email, subject=f'New notification: {notification_data.title}', text=text_content, html=html_content ) Template Example ~~~~~~~~~~~~~~~~ .. code-block:: htmlYou have a new notification:
{{ notification.message }}
Date: {{ notification.created_at|date:"F j, Y" }}
This email was sent from {{ site_url }}
Multi-Site Usage ---------------- For multi-site Django deployments, you can specify which site configuration to use: .. code-block:: python from django.contrib.sites.models import Site def send_site_specific_email(user_email, site_domain): # Get specific site site = Site.objects.get(domain=site_domain) ForwardEmailService.send_email( to=user_email, subject=f'Welcome to {site.name}!', text=f'Thank you for joining {site.name}.', site=site # Use specific site configuration ) Bulk Email Sending ------------------ For sending emails to multiple recipients, send them individually to respect rate limits: .. code-block:: python import time from django.contrib.auth.models import User def send_newsletter(subject, content): users = User.objects.filter(is_active=True, email_notifications=True) for user in users: try: ForwardEmailService.send_email( to=user.email, subject=subject, text=content, html=f'{content}
' ) # Small delay to respect rate limits time.sleep(0.1) except Exception as e: print(f"Failed to send email to {user.email}: {e}") Using as Django Email Backend ----------------------------- You can configure django-forwardemail as your default Django email backend: .. code-block:: python # settings.py EMAIL_BACKEND = 'django_forwardemail.backends.ForwardEmailBackend' Then use Django's standard email functions: .. code-block:: python from django.core.mail import send_mail, send_mass_mail from django.core.mail import EmailMessage, EmailMultiAlternatives # Using send_mail send_mail( 'Subject', 'Message body', 'from@example.com', ['to@example.com'], fail_silently=False, ) # Using EmailMessage for more control email = EmailMessage( 'Subject', 'Message body', 'from@example.com', ['to@example.com'], reply_to=['reply@example.com'], ) email.send() # Using EmailMultiAlternatives for HTML msg = EmailMultiAlternatives( 'Subject', 'Text content', 'from@example.com', ['to@example.com'] ) msg.attach_alternative('HTML content
', "text/html") msg.send() Async Support ------------- For Django async views, wrap the email sending in ``sync_to_async``: .. code-block:: python from asgiref.sync import sync_to_async from django.http import JsonResponse async def async_send_email_view(request): email_data = { 'to': 'user@example.com', 'subject': 'Async Email', 'text': 'This email was sent from an async view', } # Wrap synchronous email sending for async context await sync_to_async(ForwardEmailService.send_email)(**email_data) return JsonResponse({'status': 'Email sent successfully'}) Error Handling -------------- Always handle potential errors when sending emails: .. code-block:: python from django_forwardemail.services import ForwardEmailService import logging logger = logging.getLogger(__name__) def safe_send_email(to, subject, message): try: ForwardEmailService.send_email( to=to, subject=subject, text=message ) logger.info(f"Email sent successfully to {to}") return True except Exception as e: logger.error(f"Failed to send email to {to}: {str(e)}") return False What Gets Raised ~~~~~~~~~~~~~~~~ ``ForwardEmailService.send_email()`` raises two kinds of errors: - ``django.core.exceptions.ImproperlyConfigured`` -- the site could not be determined, or the resolved site has no ``EmailConfiguration``. - ``Exception`` -- the ForwardEmail API request failed (a non-200 response or a network error such as a timeout or connection error). The message includes the status code and response body when available. Testing Email Functionality ---------------------------- ``ForwardEmailService.send_email()`` calls the ForwardEmail API directly and does **not** go through Django's ``EMAIL_BACKEND``, so the ``locmem`` backend and ``mail.outbox`` do not capture it. Instead, mock ``requests.post`` -- the single HTTP call the service makes: .. code-block:: python from unittest.mock import patch from django.test import TestCase from django_forwardemail.services import ForwardEmailService class EmailTestCase(TestCase): @patch('django_forwardemail.services.requests.post') def test_email_sending(self, mock_post): mock_post.return_value.status_code = 200 mock_post.return_value.json.return_value = {'id': 'abc123'} ForwardEmailService.send_email( to='test@example.com', subject='Test Email', text='Test message', ) mock_post.assert_called_once() args, kwargs = mock_post.call_args self.assertEqual(kwargs['json']['to'], 'test@example.com') self.assertEqual(kwargs['json']['subject'], 'Test Email') Best Practices -------------- 1. **Always Handle Errors**: Email sending can fail for various reasons 2. **Use Templates**: Render email content using Django templates 3. **Provide Plain Text**: Always include plain text versions of HTML emails 4. **Respect Rate Limits**: Don't send too many emails too quickly 5. **Log Email Activity**: Keep track of sent emails for debugging 6. **Test Thoroughly**: Test email functionality in different environments 7. **Use Appropriate From Addresses**: Use recognizable from addresses 8. **Include Unsubscribe Links**: For marketing emails, include unsubscribe options