BERTrend includes email functionality for sending newsletters automatically. This guide explains how to configure email sending using Gmail OAuth and provides alternatives for other email providers.
The mail functionality in BERTrend is primarily used for:
- Newsletter Distribution: Automatically sending generated newsletters to configured recipients
- Report Delivery: Sending topic analysis reports and summaries via email
- Automated Notifications: Delivering scheduled content based on data feeds and topic modeling results
BERTrend uses Gmail API with OAuth 2.0 authentication for secure email sending. This requires setting up Google Cloud credentials.
- Go to the Google Cloud Console
- Create a new project or select an existing one
- Enable the Gmail API:
- Navigate to "APIs & Services" > "Library"
- Search for "Gmail API" and enable it
- Go to "APIs & Services" > "Credentials"
- Click "Create Credentials" > "OAuth client ID"
- Choose "Desktop application" as the application type
- Give it a name (e.g., "BERTrend Newsletter")
- Download the JSON file
- Place the downloaded JSON file at:
bertrend_apps/config/gmail_credentials.json - Ensure the file has the following structure:
{ "installed": { "client_id": "your-client-id", "project_id": "your-project-id", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_secret": "your-client-secret", "redirect_uris": ["http://localhost"] } }
When running BERTrend's newsletter functionality for the first time:
- The system will automatically open a browser window
- Sign in with the Gmail account you want to use for sending
- Grant permissions for BERTrend to send emails
- The system will create a
gmail_token.jsonfile automatically - Subsequent runs will use this token (refreshing as needed)
In your newsletter TOML configuration file, specify recipients:
[newsletter]
recipients = "['recipient1@example.com', 'recipient2@example.com']"
title = "Your Newsletter Title"
# ... other newsletter settingsIf you prefer not to use Gmail or need to use a different email provider, you can modify the mail functionality.
The file bertrend_apps/common/mail_utils.py contains the mail implementation. Here's how to adapt it for other
providers:
Replace the Gmail API implementation with SMTP:
import smtplib
from email.message import EmailMessage
from email.utils import COMMASPACE
import mimetypes
from pathlib import Path
# SMTP Configuration
SMTP_SERVER = "smtp.your-provider.com" # e.g., "smtp.office365.com" for Outlook
SMTP_PORT = 587
SMTP_USERNAME = "your-email@domain.com"
SMTP_PASSWORD = "your-password" # Consider using environment variables
def send_email_smtp(
subject: str,
recipients: list[str],
content: str | Path,
content_type: str = "html",
file_name: str = None,
) -> None:
"""Send email using SMTP"""
try:
msg = EmailMessage()
msg["Subject"] = subject
msg["From"] = SMTP_USERNAME
msg["To"] = COMMASPACE.join(recipients)
# Handle file attachment or content
if isinstance(content, Path) and content.is_file():
# File attachment logic (similar to original)
# ... (adapt the file attachment code from original)
else:
# Content as body
subtype = "plain" if content_type.lower() in {"md", "text", "txt"} else content_type
msg.set_content(content, subtype=subtype)
# Send via SMTP
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
server.starttls()
server.login(SMTP_USERNAME, SMTP_PASSWORD)
server.send_message(msg)
logger.debug("Email successfully sent via SMTP.")
except Exception as err:
logger.exception("SMTP error: ", err)For SendGrid example:
import sendgrid
from sendgrid.helpers.mail import Mail
SENDGRID_API_KEY = "your-sendgrid-api-key"
def send_email_sendgrid(
subject: str, recipients: list[str], content: str, content_type: str = "html"
) -> None:
"""Send email using SendGrid API"""
try:
sg = sendgrid.SendGridAPIClient(api_key=SENDGRID_API_KEY)
message = Mail(
from_email="sender@example.com",
to_emails=recipients,
subject=subject,
html_content=content if content_type == "html" else None,
plain_text_content=content if content_type != "html" else None,
)
response = sg.send(message)
logger.debug(f"SendGrid email sent, status: {response.status_code}")
except Exception as err:
logger.exception("SendGrid error: ", err)Make the email backend configurable via environment variables:
import os
EMAIL_BACKEND = os.getenv("BERTREND_EMAIL_BACKEND", "gmail") # gmail, smtp, sendgrid
def send_email(credentials, subject: str, recipients: list[str], content, **kwargs):
"""Send email using configured backend"""
if EMAIL_BACKEND == "gmail":
return send_email_gmail(credentials, subject, recipients, content, **kwargs)
elif EMAIL_BACKEND == "smtp":
return send_email_smtp(subject, recipients, content, **kwargs)
elif EMAIL_BACKEND == "sendgrid":
return send_email_sendgrid(subject, recipients, content, **kwargs)
else:
raise ValueError(f"Unsupported email backend: {EMAIL_BACKEND}")When modifying mail_utils.py, ensure you also update the import and function calls in:
bertrend_apps/newsletters/__main__.py(lines 37, 204, 208)
For non-Gmail solutions, you might not need the get_credentials() function, so adapt the newsletter code accordingly:
# Instead of:
credentials = get_credentials()
send_email(credentials=credentials, ...)
# Use:
send_email(...) # for SMTP or API-based solutions- Keep
gmail_credentials.jsonandgmail_token.jsonsecure - Add these files to your
.gitignore - Use project-specific Google Cloud projects for better isolation
- Use environment variables for sensitive credentials
- Consider using application-specific passwords
- Enable two-factor authentication on email accounts
- For production, use dedicated email service accounts
- Token expired: Delete
gmail_token.jsonand re-authenticate - Insufficient permissions: Ensure Gmail API is enabled and OAuth consent screen is configured
- Rate limiting: Gmail API has sending limits; consider batching for large recipient lists
- Firewall/Network: Ensure outbound connections are allowed (port 587 for SMTP, 443 for APIs)
- Spam filters: Configure SPF/DKIM records for better deliverability
- Large attachments: Consider file size limits (Gmail: 25MB, others vary)
To test your email setup:
- Create a simple test script:
from bertrend.bertrend_apps.common import get_credentials, send_email
# For Gmail OAuth
credentials = get_credentials()
send_email(
credentials=credentials,
subject="BERTrend Test Email",
recipients=["your-test-email@example.com"],
content="<h1>Test successful!</h1>",
content_type="html",
)- Run the newsletter functionality with a small test configuration to verify end-to-end functionality.