# Copyright 2018 Google LLC. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from email.mime import text import email.utils import smtplib import socket import mailjet_rest from scoreboard import main app = main.get_app() class MailFailure(Exception): """Inability to send mail.""" pass def send(message, subject, to, to_name=None, sender=None, sender_name=None): """Send an email.""" sender = sender or app.config.get('MAIL_FROM') sender_name = sender_name or app.config.get('MAIL_FROM_NAME') or '' mail_provider = app.config.get('MAIL_PROVIDER') if mail_provider is None: app.logger.error('No MAIL_PROVIDER configured!') raise MailFailure('No MAIL_PROVIDER configured!') elif mail_provider == 'smtp': _send_smtp(message, subject, to, to_name, sender, sender_name) elif mail_provider == 'mailjet': _send_mailjet(message, subject, to, to_name, sender, sender_name) else: app.logger.error('Invalid MAIL_PROVIDER configured!') raise MailFailure('Invalid MAIL_PROVIDER configured!') def _send_smtp(message, subject, to, to_name, sender, sender_name): """SMTP implementation of sending email.""" host = app.config.get('MAIL_HOST') if not host: raise MailFailure('SMTP Server Not Configured') try: server = smtplib.SMTP(host) except (smtplib.SMTPConnectError, socket.error) as ex: app.logger.error('Unable to send mail: %s', str(ex)) raise MailFailure('Error connecting to SMTP server.') msg = text.MIMEText(message) msg['Subject'] = subject msg['To'] = email.utils.formataddr((to_name, to)) msg['From'] = email.utils.formataddr((sender_name, sender)) try: if app.debug: server.set_debuglevel(True) server.sendmail(sender, [to], msg.as_string()) except (smtplib.SMTPException, socket.error) as ex: app.logger.error('Unable to send mail: %s', str(ex)) raise MailFailure('Error sending mail to SMTP server.') finally: try: server.quit() except smtplib.SMTPException: pass def _send_mailjet(message, subject, to, to_name, sender, sender_name): """Mailjet implementation of sending email.""" api_key = app.config.get('MJ_APIKEY_PUBLIC') api_secret = app.config.get('MJ_APIKEY_PRIVATE') if not api_key or not api_secret: app.logger.error('Missing MJ_APIKEY_PUBLIC/MJ_APIKEY_PRIVATE!') return # Note the data structures we use are api v3.1 client = mailjet_rest.Client( auth=(api_key, api_secret), api_url='https://api.mailjet.com/', version='v3.1') from_obj = { "Email": sender, } if sender_name: from_obj["Name"] = sender_name to_obj = [{ "Email": to, }] if to_name: to_obj[0]["Name"] = to_name message = { "From": from_obj, "To": to_obj, "Subject": subject, "TextPart": message, } result = client.send.create(data={'Messages': [message]}) if result.status_code != 200: app.logger.error( 'Error sending via mailjet: (%d) %r', result.status_code, result.text) raise MailFailure('Error sending via mailjet!') try: j = result.json() except Exception: app.logger.error('Error sending via mailjet: %r', result.text) raise MailFailure('Error sending via mailjet!') if j['Messages'][0]['Status'] != 'success': app.logger.error('Error sending via mailjet: %r', j) raise MailFailure('Error sending via mailjet!')