l1dge / techswap

Repo for the techswap project
2 stars 0 forks source link

Use email on Heroku #54

Closed bbelderbos closed 3 years ago

bbelderbos commented 3 years ago

You can provision Twilio's Sendgrid through Heroku. It will create an account and possibly the API key you'll need (if not you need to login and generate one yourself).

Set this key in your Heroku settings as say SENDGRID_API_KEY

Then on the platform we have this in our settings.py for email:

# need to set these for Django's native PW reset emails
EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_HOST_USER = 'apikey'
EMAIL_HOST_PASSWORD = config('SENDGRID_API_KEY')
EMAIL_PORT = 587
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = '...'

if ENV == 'local':  # in your case this could be "if DEBUG:"
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
else:
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
bbelderbos commented 3 years ago

Ah and we had to install the sendgrid package as well:

$ ag sendgrid
requirements.txt
44:sendgrid==6.4.8

And this is our convoluted email function, you can simplify this of course, but it will save you some time:

import sendgrid
from sendgrid.helpers.mail import To, From, Mail

from logs.models import EmailSent

FROM_EMAIL = config('FROM_EMAIL')  # notification email
ADMIN_EMAIL = config('ADMIN_EMAIL')  # admin email
ME = 'me'
ALL = 'all'
PYBITES = 'PyBites'

sg = sendgrid.SendGridAPIClient(api_key=config('SENDGRID_API_KEY'))

def send_email(to_email, subject, body,
               from_email=FROM_EMAIL,
               display_name=PYBITES,
               html=True, log=True):

    # log message
    to_email_for_log = to_email if log else ALL

    # newlines get wrapped in email, use html
    body = body.replace('\n', '<br>')

    try:
        obj, created = EmailSent.objects.get_or_create(
                to_email=to_email_for_log,
                subject=subject,
                content=body)
    except IntegrityError:
        pass

    # if local no emails
    if settings.LOCAL:
        print('local env - no email, only print send_email args:')
        print('to_email: {}'.format(to_email))
        print('subject: {}'.format(subject))
        print('body: {}'.format(body))
        print('from_email: {}'.format(from_email))
        print('html: {}'.format(html))
        print()
        return

    from_email = From(email=from_email, name=display_name)

    to_email = ADMIN_EMAIL if to_email == 'me' else to_email
    to_email = To(to_email)

    # https://github.com/sendgrid/sendgrid-python/blob/master/sendgrid/helpers/mail/mail.py
    message = Mail(
        from_email=from_email,
        to_emails=to_email,
        subject=subject,
        plain_text_content=body if not html else None,
        html_content=body if html else None
    )

    response = sg.send(message)

    if str(response.status_code)[0] != '2':
        # TODO logging
        print(f'ERROR sending message, status_code {response.status_code}')

    return response

HTH Bob

l1dge commented 3 years ago

Sendgrid didn't work for me, account was disabled as soon as it was created. Went with my hosting provide smtp server. All seems to work.