def send_email(from_address: str, to_addresses: list, subject: str, body_html: str, cc_addresses: list=None, bcc_addresses: list=None, attachment_list: list=None): api_key = config.sendgrid['api_token'] sg = SendGridAPIClient(api_key=api_key) email = Mail(from_email=from_address, to_emails=to_addresses, subject=subject, html_content=body_html) for e in cc_addresses: email.add_cc(e) for e in bcc_addresses: email.add_bcc(e) for att_tuple in attachment_list: filename = att_tuple[0] column_names = att_tuple[1] data = att_tuple[2] att = create_attachment_csv(filename, column_names, data) email.add_attachment(att) try: resp = sg.send(email) except Exception as ex: logging.exception(ex)
def create_ticket_message(ticket): event = ticket.article.event tmpl = loader.get_template('events/email/ticket_message.md') subject = 'Entrada para {}'.format(event.name) body = tmpl.render({ 'ticket': ticket, 'article': ticket.article, 'category': ticket.article.category, 'event': event, }) mail = Mail(from_email=Email(settings.CONTACT_EMAIL, settings.ASSOCIATION_NAME), subject=subject, to_email=Email(ticket.customer_email), content=Content('text/html', as_markdown(body))) attachment = Attachment() pdf_filename = ticket.as_pdf() with open(pdf_filename, 'rb') as f: data = f.read() attachment.content = base64.b64encode(data).decode() attachment.type = 'application/pdf' attachment.filename = 'ticket.pdf' attachment.disposition = 'attachment' mail.add_attachment(attachment) return mail
def send_email_task_sendgrid(payload, headers, smtp_config): try: message = Mail(from_email=From(payload['from'], payload['fromname']), to_emails=payload['to'], subject=payload['subject'], html_content=payload["html"]) if payload['attachments'] is not None: for attachment in payload['attachments']: with open(attachment, 'rb') as f: file_data = f.read() f.close() encoded = base64.b64encode(file_data).decode() attachment = Attachment() attachment.file_content = FileContent(encoded) attachment.file_type = FileType('application/pdf') attachment.file_name = FileName(payload['to']) attachment.disposition = Disposition('attachment') message.add_attachment(attachment) sendgrid_client = SendGridAPIClient(get_settings()['sendgrid_key']) logging.info('Sending an email regarding {} on behalf of {}'.format( payload["subject"], payload["from"])) sendgrid_client.send(message) logging.info('Email sent successfully') except urllib.error.HTTPError as e: if e.code == 429: logging.warning("Sendgrid quota has exceeded") send_email_task_smtp.delay(payload=payload, headers=None, smtp_config=smtp_config) elif e.code == 554: empty_attachments_send(sendgrid_client, message) else: logging.exception( "The following error has occurred with sendgrid-{}".format( str(e)))
def send_mail(from_user: tuple, to: list, subject: str, content: str, attachments=None) -> bool: if attachments is None: attachments = [] # Bail out if SendGrid API key has not been set if SENDGRID_API_KEY is None: return False # Create a Content object html_content = Content('text/html', content) # Create a Mail object mail = Mail(from_user, to, subject, html_content) # Add attachments, if any for attachment in attachments: try: mail.add_attachment( Attachment(attachment['data'], attachment['filename'], attachment['type'])) except KeyError: return False # Actually send the email try: SendGridAPIClient(SENDGRID_API_KEY).send(mail) except Exception as e: log('Exception occurred while sending mail!') log(e) return False return True
def construct_email(mailfrom: str, mailto: list, subject: str, content: str, attfilename: str, data: str): """ still intake one mailfrom and one mailto for now params: mailfrom: an email, mailto: an email, subject: str, data: csv-ready string attfilename: filename for attachment """ mail = Mail() mail.from_email = Email(mailfrom) mail.subject = subject mail.add_content(Content("text/html", content)) personalization = Personalization() for i in mailto: personalization.add_to(Email(i)) mail.add_personalization(personalization) attachment = Attachment() attachment.content = str(base64.b64encode(data.encode('utf-8')), 'utf-8') attachment.type = 'text/csv' attachment.filename = attfilename attachment.disposition = 'attachment' mail.add_attachment(attachment) return mail
def send(self, config, subject, body, img, row): content = Content("text/html", body) attachment = Attachment() attachment.content = img attachment.type = "image/jpeg" attachment.filename = "qrcode.jpg" attachment.disposition = "inline" attachment.content_id = "qrcode" fromaddr = Email(config.from_email) toaddr = Email(row['email']) mail = Mail(fromaddr, subject, toaddr, content) mail.add_attachment(attachment) try: response = self.sg.client.mail.send.post(request_body=mail.get()) except urllib.HTTPError as err: print(err.read()) exit() print(response.status_code) print(response.body) print(response.headers)
def sendMailWithAttachment(context): # print(context) html_version = 'email/email.html' message = Mail( from_email='*****@*****.**', to_emails=context['emails'], subject="Reg: Payment remittance for {} ${} {} Vendor : {}".format( context["clearing_date"], context["amount"], context["currency"], context["supplier"]), html_content=render_to_string(html_version, {'context': context})) with open(context['attachment'], 'rb') as f: data = f.read() f.close() print(data) encoded = base64.b64encode(data).decode() attachment = Attachment() attachment.file_content = FileContent(encoded) attachment.file_type = FileType('text/csv') attachment.file_name = FileName(context['attachment']) attachment.disposition = Disposition('attachment') attachment.content_id = ContentId('REMITTANCE') message.add_attachment(attachment) try: sg = SendGridAPIClient( "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" ) response = sg.send(message) print(response.status_code) print(response.body) print(response.headers) except Exception as e: print(e) # sendMailWithAttachment()
def _build_sg_mail(self, email): mail = Mail() from_name, from_email = rfc822.parseaddr(email.from_email) # Python sendgrid client should improve # sendgrid/helpers/mail/mail.py:164 if not from_name: from_name = None mail.set_from(Email(from_email, from_name)) mail.set_subject(email.subject) personalization = Personalization() for e in email.to: personalization.add_to(Email(e)) for e in email.cc: personalization.add_cc(Email(e)) for e in email.bcc: personalization.add_bcc(Email(e)) personalization.set_subject(email.subject) mail.add_content(Content("text/plain", email.body)) if isinstance(email, EmailMultiAlternatives): for alt in email.alternatives: if alt[1] == "text/html": mail.add_content(Content(alt[1], alt[0])) elif email.content_subtype == "html": mail.contents = [] mail.add_content(Content("text/plain", ' ')) mail.add_content(Content("text/html", email.body)) if hasattr(email, 'categories'): for c in email.categories: mail.add_category(Category(c)) if hasattr(email, 'template_id'): mail.set_template_id(email.template_id) if hasattr(email, 'substitutions'): for k, v in email.substitutions.items(): personalization.add_substitution(Substitution(k, v)) for k, v in email.extra_headers.items(): mail.add_header({k: v}) for attachment in email.attachments: if isinstance(attachment, MIMEBase): attach = Attachment() attach.set_filename(attachment.get_filename()) attach.set_content(base64.b64encode(attachment.get_payload())) mail.add_attachment(attach) elif isinstance(attachment, tuple): attach = Attachment() attach.set_filename(attachment[0]) base64_attachment = base64.b64encode(attachment[1]) if sys.version_info >= (3, ): attach.set_content(str(base64_attachment, 'utf-8')) else: attach.set_content(base64_attachment) attach.set_type(attachment[2]) mail.add_attachment(attach) mail.add_personalization(personalization) return mail.get()
def get(self, request, *args, **kwargs): self.template = self.get_object(kwargs.get('tp_pk')) self.person = self.get_person(kwargs.get('to_pk'), kwargs.get('tp_pk')) mail = Mail() mail.set_from(Email(self.request.user.email)) mail.set_subject(self.template.title) personalization = Personalization() personalization.add_to(Email(self.person.email)) mail.add_personalization(personalization) body = self.render_body(self.person.name, self.template.template_email.path) mail.add_content(Content("text/html", body)) if self.template.attachment: path = self.template.attachment.path ext = path.split('.')[-1] with open(path, "rb") as f: mail.add_attachment(self.attach_file( f, ext, self.template.slug, self.template.title)) self.sg.client.mail.send.post(request_body=mail.get()) messages.info( request, """You have just send an email to <strong>{0.email}</strong> with the subject <strong>{1}</strong> """ .format(self.person, self.template.title)) self.person.email_sent = True self.person.save() return super(SendEmailView, self).get(request, *args, **kwargs)
def send_registration_mail(attendee: Attendee, event: Event): qr_data = gen_qrcode(data=str(attendee.uuid)).read() template = templates['REGISTRATION'] mail = Mail() mail.from_email = Email(template['FROM_EMAIL'], template['FROM_NAME']) mail.template_id = template['ID'] mail.add_category(Category(template['CATEGORY'])) attachment1 = Attachment() attachment1.content = base64.b64encode(qr_data).decode('ascii') attachment1.filename = template['FILENAME'] mail.add_attachment(attachment1) personalization = Personalization() personalization.add_substitution( Substitution("%first_name%", attendee.name.split()[0])) personalization.add_substitution(Substitution("%event_name%", event.name)) personalization.add_to(Email(attendee.email, attendee.name)) mail.add_personalization(personalization) try: sg.client.mail.send.post(request_body=mail.get()) return qr_data except Exception as e: raise e
def form_valid(self, form): self.template = form.cleaned_data['template'] self.email = form.cleaned_data['email'] self.subject = form.cleaned_data['subject'] mail = Mail() mail.set_from(Email(self.request.user.email)) mail.set_subject(self.subject) personalization = Personalization() personalization.add_to(Email(self.email)) mail.add_personalization(personalization) body_personalized = self.render_body( form.cleaned_data['name'], self.template.template_file.path) body = self.render_content( body_personalized, form.cleaned_data['content'], self.subject) mail.add_content(Content("text/html", body)) if form.cleaned_data['attachment']: file_name = form.cleaned_data['attachment'].name ext = file_name.split('.')[-1] with form.cleaned_data['attachment'] as f: mail.add_attachment(self.attach_file( f, ext, slugify(file_name), self.subject)) self.sg.client.mail.send.post(request_body=mail.get()) return super(CustomEmailView, self).form_valid(form)
def _create_email(self, email: dict, email_id: str) -> Mail: self.log_debug('converting email %s to sendgrid format', email_id) mail = Mail() personalization = Personalization() for i, to in enumerate(email.get('to', [])): personalization.add_to(Email(to)) self.log_debug('added to %d to email %s', i, email_id) for i, cc in enumerate(email.get('cc', [])): personalization.add_cc(Email(cc)) self.log_debug('added cc %d to email %s', i, email_id) for i, bcc in enumerate(email.get('bcc', [])): personalization.add_bcc(Email(bcc)) self.log_debug('added bcc %d to email %s', i, email_id) mail.add_personalization(personalization) self.log_debug('added recipients to email %s', email_id) mail.subject = email.get('subject', '(no subject)') self.log_debug('added subject to email %s', email_id) mail.add_content(Content('text/html', email.get('body'))) self.log_debug('added content to email %s', email_id) mail.from_email = Email(email.get('from')) self.log_debug('added from to email %s', email_id) for i, attachment in enumerate(email.get('attachments', [])): mail.add_attachment(self._create_attachment(attachment)) self.log_debug('added attachment %d to email %s', i, email_id) self.log_debug('converted email %s to sendgrid format', email_id) return mail
def update(self, instance, validated_data): user = self.context['request'].user mail_subject = 'Покупка пакета' message = render_to_string('liqpay.html', { 'pocket': validated_data['user_pocket'], }) data = { 'to_emails': [ user.email, ], 'subject': mail_subject, 'html_content': message } pdfkit.from_string('TEST', 'smart_lead_pocket_paid.pdf') from_email = settings.DEFAULT_FROM_EMAIL message = Mail( from_email=from_email, **data, ) attachment = Attachment() with open('smart_lead_pocket_paid.pdf', 'rb') as f: attachment.file_content = base64.b64encode( f.read()).decode('utf-8') attachment.file_name = 'smart_lead_pocket_paid.pdf' message.add_attachment(attachment) sg = SendGridAPIClient(settings.SENDGRID_API_KEY) sg.send(message) # send_email_task.delay(**data) return super().update(instance, validated_data)
def sendlog(): sg = sendgrid.SendGridAPIClient(apikey=os.environ['SENDGRID_API_KEY']) contentString = "bi-weekly refactoring roundup" attachment = Attachment() attachment.content = encodefile('log/out.txt') attachment.type = 'text/plain' attachment.filename = 'log/out.txt' attachment.disposition = 'attachment' attachment.content_id = 'log' from_email = Email('*****@*****.**') to_email = Email('*****@*****.**') subject = 'refactoring roundup' content = Content('text/plain', contentString) mail = Mail(from_email, subject, to_email, content) mail.add_attachment(attachment) mail.personalizations[0].add_cc(Email('*****@*****.**')) response = sg.client.mail.send.post(request_body=mail.get()) print(response.status_code) print(response.body) print(response.headers)
def send_messages(self, email_messages): sg = sendgrid.SendGridAPIClient(api_key=self.api_key) for email_message in email_messages: mail = Mail( from_email=email_message.from_email, to_emails=email_message.to, subject=email_message.subject, html_content=HtmlContent(email_message.body), ) for attachment in email_message.attachments: mail.add_attachment(Attachment( file_name=attachment[0], file_content=base64.b64encode(attachment[1]).decode(), file_type=attachment[2], )) try: response = sg.client.mail.send.post(request_body=mail.get()) if response.status_code // 100 != 2: error_message = ( f'Email "{email_message.subject}" was not sent to {email_message.to}. ' f'Status is {response.status_code}' ) if self.fail_silently: logger.error(error_message) else: raise SendGridBadStatusError(error_message) except HTTPError as error: if self.fail_silently: if type(error) == ForbiddenError: logger.exception(f'Email {email_message.subject} was not sent to {email_message.to} - {error.to_dict}') else: logger.exception(f'Email {email_message.subject} was not sent to {email_message.to} - {error}') else: raise
def send_email(to, subject, html_content, files=None, dryrun=False, cc=None, bcc=None, mime_subtype='mixed', **kwargs): """ Send an email with html content using sendgrid. To use this plugin: 0. include sendgrid subpackage as part of your Airflow installation, e.g., pip install airflow[sendgrid] 1. update [email] backend in airflow.cfg, i.e., [email] email_backend = airflow.contrib.utils.sendgrid.send_email 2. configure Sendgrid specific environment variables at all Airflow instances: SENDGRID_MAIL_FROM={your-mail-from} SENDGRID_API_KEY={your-sendgrid-api-key}. """ mail = Mail() mail.from_email = Email(os.environ.get('SENDGRID_MAIL_FROM')) mail.subject = subject # Add the recipient list of to emails. personalization = Personalization() to = get_email_address_list(to) for to_address in to: personalization.add_to(Email(to_address)) if cc: cc = get_email_address_list(cc) for cc_address in cc: personalization.add_cc(Email(cc_address)) if bcc: bcc = get_email_address_list(bcc) for bcc_address in bcc: personalization.add_bcc(Email(bcc_address)) # Add custom_args to personalization if present pers_custom_args = kwargs.get('personalization_custom_args', None) if isinstance(pers_custom_args, dict): for key in pers_custom_args.keys(): personalization.add_custom_arg(CustomArg(key, pers_custom_args[key])) mail.add_personalization(personalization) mail.add_content(Content('text/html', html_content)) categories = kwargs.get('categories', []) for cat in categories: mail.add_category(Category(cat)) # Add email attachment. for fname in files or []: basename = os.path.basename(fname) attachment = Attachment() with open(fname, "rb") as f: attachment.content = base64.b64encode(f.read()) attachment.type = mimetypes.guess_type(basename)[0] attachment.filename = basename attachment.disposition = "attachment" attachment.content_id = '<%s>' % basename mail.add_attachment(attachment) _post_sendgrid_mail(mail.get())
def sendExperimentResults(config): try: from sendgrid import SendGridAPIClient from sendgrid.helpers.mail import (Mail, Attachment, FileContent, FileName, FileType, Disposition, ContentId) message = Mail( from_email='*****@*****.**', to_emails='*****@*****.**', subject=f'Experiment results: {config.configurationDirectory}', html_content= f'These are your results for {config.configurationDirectory}. Please see the attached charts.' ) for file in config.listAllFilesInFolder("charts"): data = config.loadKwolaFileData("charts", file) encoded = base64.b64encode(data).decode() attachment = Attachment() attachment.file_content = FileContent(encoded) attachment.file_type = FileType('image/png') attachment.file_name = FileName(file) attachment.disposition = Disposition('attachment') attachment.content_id = ContentId(file) message.add_attachment(attachment) videoFiles = config.listAllFilesInFolder("debug_videos") videoFiles = sorted( videoFiles, key=lambda fileName: pathlib.Path( os.path.join(config.configurationDirectory, "debug_videos", fileName)).stat().st_mtime, reverse=True) for file in videoFiles[:2]: data = config.loadKwolaFileData("debug_videos", file) encoded = base64.b64encode(data).decode() attachment = Attachment() attachment.file_content = FileContent(encoded) attachment.file_type = FileType('video/mpeg') attachment.file_name = FileName(file) attachment.disposition = Disposition('attachment') attachment.content_id = ContentId(file) message.add_attachment(attachment) if 'sendgrid_api_key' in config: apiKey = config['sendgrid_api_key'] elif 'SENDGRID_API_KEY' in os.environ: apiKey = os.environ.get('SENDGRID_API_KEY') else: getLogger().error( "There was no API key provided for Sendgrid. Please set sendgrid_api_key within your config.json file." ) return sg = SendGridAPIClient(apiKey) response = sg.send(message) except Exception: getLogger().error(traceback.format_exc())
def sendemail(to=None, from_=None, subject=None, body=None, attachments=None, reply_to=None): """ Send email :param to: receiver :param from_: sender :param subject: subject :param body: Email body :param attachments: Attachments """ if to is None: to = [] if attachments is None: attachments = [] if not subject: subject = "User not recognized" if not body: body = "Please email support at %s" % SUPPORT_EMAIL to = list(set(to)) # no duplicates. sg = sendgrid.SendGridAPIClient(apikey=SENDGRID_API_KEY) from_email = Email(from_ or SUPPORT_EMAIL) if reply_to is not None: from_email = Email(reply_to) to_email = Email(to[0]) content = Content("text/html", markdown(body)) mail = Mail(from_email, subject, to_email, content) if reply_to is not None: mail.reply_to = Email(reply_to) if len(to) > 1: for receiver in to[1:]: mail.personalizations[0].add_to(Email(receiver)) for attachment in attachments: mail.add_attachment(build_attachment(attachment)) try: print('Now trying to send an email') response = sg.client.mail.send.post(request_body=mail.get()) print("Email sent.. %s" % response.status_code) return response.status_code, response.body except Exception as e: print(e) raise e
def _prepare_sendgrid_data(self): self.ensure_one() s_mail = Mail() s_mail.set_from(Email(self.email_from)) if self.reply_to: s_mail.set_reply_to(Email(self.reply_to)) s_mail.add_custom_arg(CustomArg('odoo_id', self.message_id)) html = self.body_html or ' ' p = re.compile(r'<.*?>') # Remove HTML markers text_only = self.body_text or p.sub('', html.replace('<br/>', '\n')) s_mail.add_content(Content("text/plain", text_only)) s_mail.add_content(Content("text/html", html)) test_address = config.get('sendgrid_test_address') # We use only one personalization for transactional e-mail personalization = Personalization() personalization.set_subject(self.subject or ' ') addresses = list() if not test_address: if self.email_to and self.email_to not in addresses: personalization.add_to(Email(self.email_to)) addresses.append(self.email_to) for recipient in self.recipient_ids: if recipient.email not in addresses: personalization.add_to(Email(recipient.email)) addresses.append(recipient.email) if self.email_cc and self.email_cc not in addresses: personalization.add_cc(Email(self.email_cc)) else: _logger.info('Sending email to test address {}'.format( test_address)) personalization.add_to(Email(test_address)) self.email_to = test_address if self.sendgrid_template_id: s_mail.set_template_id(self.sendgrid_template_id.remote_id) for substitution in self.substitution_ids: personalization.add_substitution(Substitution( substitution.key, substitution.value)) s_mail.add_personalization(personalization) for attachment in self.attachment_ids: s_attachment = Attachment() # Datas are not encoded properly for sendgrid s_attachment.set_content(base64.b64encode(base64.b64decode( attachment.datas))) s_attachment.set_filename(attachment.name) s_mail.add_attachment(s_attachment) return s_mail.get()
def send_certificate_mail(name, email, event, cpf=None): template = templates['CERTIFICATE_EMITTED'] mail = Mail() mail.from_email = Email(template['FROM_EMAIL'], template['FROM_NAME']) mail.template_id = template['ID'] mail.add_category(Category(template['CATEGORY'])) attachment1 = Attachment() if isinstance(event, Event): event_place = event.place event_duration = event.formated_duration event_date = event.formated_dates event_min_percent = event.certificate_minimum_time else: event_place = event.event_day.event.place event_duration = event.event_day.event.formated_duration event_date = event.event_day.event.formated_dates event_min_percent = event.event_day.event.certificate_minimum_time cpf_text = _(', bearer of the registry number %(cpf)s,') % { 'cpf': cpf } if cpf else '' data = { 'name': name, 'event': event.name, 'cpf': cpf_text, 'event_date': event_date, 'event_place': event_place, 'event_duration': event_duration, 'event_min_percent': event_min_percent } certificate_data = event.certificate_model.generate_certificate(data) attachment1.content = base64.b64encode( certificate_data.read()).decode('ascii') attachment1.filename = template['FILENAME'] mail.add_attachment(attachment1) personalization = Personalization() personalization.add_substitution( Substitution("%first_name%", name.split()[0])) personalization.add_substitution(Substitution("%event_name%", event.name)) personalization.add_to(Email(email, name)) mail.add_personalization(personalization) try: response = sg.client.mail.send.post(request_body=mail.get()) return True except Exception as e: print(response.body) raise e
def _create_email(self, email: dict, email_id: str) -> Mail: self.log_debug('converting email %s to sendgrid format', email_id) mail = Mail() personalization = Personalization() for i, to in enumerate(email.get('to', [])): personalization.add_to(Email(to)) self.log_debug('added to %d to email %s', i, email_id) for i, cc in enumerate(email.get('cc', [])): personalization.add_cc(Email(cc)) self.log_debug('added cc %d to email %s', i, email_id) for i, bcc in enumerate(email.get('bcc', [])): personalization.add_bcc(Email(bcc)) self.log_debug('added bcc %d to email %s', i, email_id) mail.add_personalization(personalization) self.log_debug('added recipients to email %s', email_id) mail.subject = email.get('subject', '(no subject)') self.log_debug('added subject to email %s', email_id) mail.add_content( Content('text/html', email.get('body', '(no content)'))) self.log_debug('added content to email %s', email_id) # at some point SendGrid had the ability to send from subdomains of a verified # domain, so verifying {domain} let us send from {client}.{domain} # ...this feature went away so the following is a work-around which # changes the from address to the verified root domain but using reply-to # so that the email still gets routed back to the original client # ...this is a pretty ugly hack and the real fix is to change the logic of # how we sign up users on clients to use the new format {user}-{client}@{domain} from_email = email.get('from') if from_email: user, client_domain = from_email.split('@') client_domain_parts = client_domain.split('.') if len(client_domain_parts) == 3: client = client_domain_parts[0] domain = '.'.join(client_domain_parts[1:]) mail.from_email = Email('{}-{}@{}'.format( user, client, domain)) mail.reply_to = Email(from_email) else: mail.from_email = Email(from_email) self.log_debug('added from to email %s', email_id) for i, attachment in enumerate(email.get('attachments', [])): mail.add_attachment(self._create_attachment(attachment)) self.log_debug('added attachment %d to email %s', i, email_id) self.log_debug('converted email %s to sendgrid format', email_id) return mail
def send_email(to, subject, html_content, files=None, dryrun=False, cc=None, bcc=None, mime_subtype='mixed', **kwargs): """ Send an email with html content using sendgrid. To use this plugin: 0. include sendgrid subpackage as part of your Airflow installation, e.g., pip install airflow[sendgrid] 1. update [email] backend in airflow.cfg, i.e., [email] email_backend = airflow.contrib.utils.sendgrid.send_email 2. configure Sendgrid specific environment variables at all Airflow instances: SENDGRID_MAIL_FROM={your-mail-from} SENDGRID_API_KEY={your-sendgrid-api-key}. """ mail = Mail() mail.from_email = Email(os.environ.get('SENDGRID_MAIL_FROM')) mail.subject = subject # Add the recipient list of to emails. personalization = Personalization() to = get_email_address_list(to) for to_address in to: personalization.add_to(Email(to_address)) if cc: cc = get_email_address_list(cc) for cc_address in cc: personalization.add_cc(Email(cc_address)) if bcc: bcc = get_email_address_list(bcc) for bcc_address in bcc: personalization.add_bcc(Email(bcc_address)) mail.add_personalization(personalization) mail.add_content(Content('text/html', html_content)) # Add custom_args to personalization if present pers_custom_args = kwargs.get('personalization_custom_args', None) if isinstance(pers_custom_args, dict): for key in pers_custom_args.keys(): personalization.add_custom_arg(CustomArg(key, pers_custom_args[key])) # Add email attachment. for fname in files or []: basename = os.path.basename(fname) attachment = Attachment() with open(fname, "rb") as f: attachment.content = base64.b64encode(f.read()) attachment.type = mimetypes.guess_type(basename)[0] attachment.filename = basename attachment.disposition = "attachment" attachment.content_id = '<%s>' % basename mail.add_attachment(attachment) _post_sendgrid_mail(mail.get())
def _make_sendgrid_mail(self, message): mail = Mail() if message.sender: mail.from_email = Email(message.sender) else: mail.from_email = Email(self.default_sender) if message.mail_options and message.mail_options.get('from_name'): mail.from_email.name = message.mail_options.get('from_name') template_id = getattr(message, 'template_id', None) if template_id: mail.template_id = template_id if message.subject: mail.subject = message.subject if message.recipients: if type(message.recipients) == list: personalization = Personalization() for recipient in message.recipients: personalization.add_to(Email(recipient)) dynamic_template_data = getattr(message, 'dynamic_template_data', None) if dynamic_template_data: personalization.dynamic_template_data = dynamic_template_data mail.add_personalization(personalization) else: raise Exception("unsupported type yet") if message.body: mail.add_content(Content("text/plain", message.body)) if message.html: mail.add_content(Content("text/html", message.html)) if message.reply_to: mail.reply_to = Email(message.reply_to) if message.attachments: for attachment in message.attachments: file_content = base64.b64encode( attachment.data).decode('UTF-8') mail.add_attachment( Attachment( file_content=file_content, file_name=attachment.filename, file_type=attachment.content_type, disposition=attachment.disposition, )) return mail
def submit(): """Take data from the form, generate, display, and email QR code to user.""" table = P5November2019 event_name = "Problem Solving with Game Development" id = get_current_id(table) user = table(id=id, username=current_user.username, email=current_user.email, phone=current_user.phone) img = generate_qr(user) img.save("qr.png") img_data = open("qr.png", "rb").read() encoded = base64.b64encode(img_data).decode() try: db.session.add(user) db.session.commit() except exc.IntegrityError as e: print(e) return """It appears there was an error while trying to enter your data into our database.<br/>Kindly contact someone from the team and we will have this resolved ASAP""" name = current_user.username from_email = "*****@*****.**" to_email = [(user.email, name)] date = datetime.now().strftime("%B,%Y") subject = "Registration for {} - {} - ID {}".format(event_name, date, id) message = """<img src='https://drive.google.com/uc?id=12VCUzNvU53f_mR7Hbumrc6N66rCQO5r-&export=download' style="width:30%;height:50%"> <hr> {}, your registration is done! <br/> A QR code has been attached below! <br/> You're <b>required</b> to present this on the day of the event.""".format(name) content = Content("text/html", message) mail = Mail(from_email, to_email, subject, html_content=content) mail.add_attachment(Attachment(encoded, "qr.png", "image/png")) try: response = SendGridAPIClient(SENDGRID_API_KEY).send(mail) print(response.status_code) print(response.body) print(response.headers) except Exception as e: print(e) return 'Please save this QR Code. It has also been emailed to you.<br><img src=\ "data:image/png;base64, {}"/>'.format(encoded)
def add_attachments( mail: Mail, attachments: Union[List[Dict[str, Any]], Dict[str, Any]]) -> Mail: if isinstance(attachments, dict): attachments = [attachments] for att_dict in attachments: attachment = Attachment() attachment.content = att_dict["content"] attachment.filename = att_dict["filename"] attachment.type = att_dict.get("type") attachment.disposition = att_dict.get("disposition") mail.add_attachment(attachment) return mail
def send(self, message, envelope_from=None): assert message.send_to, "No recipients have been added" assert message.sender, ( "The message does not specify a sender and a default sender " "has not been configured") if message.has_bad_headers(): raise BadHeaderError if message.date is None: message.date = time.time() if not message.subject: message.subject = word("(no subject)") sgmessage = SGMail( from_email=Email(message.sender), to_emails=[ To(addressee) for addressee in sanitize_addresses(message.recipients) ], subject=message.subject, plain_text_content=message.body, html_content=message.html) if message.reply_to: sgmessage.reply_to = ReplyTo(message.reply_to) if message.cc: for recipient in list(sanitize_addresses(message.cc)): sgmessage.add_cc(recipient) if message.bcc: for recipient in list(sanitize_addresses(message.bcc)): sgmessage.add_bcc(recipient) if message.attachments: for flask_attachment in message.attachments: attachment = Attachment() attachment.file_content = FileContent( base64.b64encode(flask_attachment.data).decode()) attachment.file_type = FileType(flask_attachment.content_type) attachment.file_name = FileName(flask_attachment.filename) attachment.disposition = Disposition( flask_attachment.disposition) sgmessage.add_attachment(attachment) sg = SendGridAPIClient(self.mail.api_key) response = sg.send(sgmessage) if response.status_code >= 400: sys.stderr.write("SendGrid status code: " + str(response.status_code) + "\n") sys.stderr.write("SendGrid response headers: " + repr(response.headers) + "\n") try: sys.stderr.write(repr(response.body) + "\n") except: pass raise Exception("Failed to send e-mail message to SendGrid") email_dispatched.send(message, app=current_app._get_current_object())
def send_emails_via_sendgrid(encoded_img: "base 64 string"): attachment = Attachment() attachment.content = encoded_img attachment.type = "image/jpeg" attachment.filename = "fallen.jpeg" attachment.disposition = "inline" attachment.content_id = "fallen-picture" for to_email in to_emails: email_data = Mail(from_email, subject, to_email, content) email_data.add_attachment(attachment) response = sgclient.client.mail.send.post( request_body=email_data.get()) print("email status: {}".format(response.status_code))
def _prepare_sendgrid_data(self): self.ensure_one() s_mail = Mail() s_mail.set_from(Email(self.email_from)) s_mail.set_reply_to(Email(self.reply_to)) s_mail.add_custom_arg(CustomArg('odoo_id', self.message_id)) html = self.body_html or ' ' p = re.compile(r'<.*?>') # Remove HTML markers text_only = self.body_text or p.sub('', html.replace('<br/>', '\n')) s_mail.add_content(Content("text/plain", text_only)) s_mail.add_content(Content("text/html", html)) test_address = config.get('sendgrid_test_address') # TODO For now only one personalization (transactional e-mail) personalization = Personalization() personalization.set_subject(self.subject or ' ') if not test_address: if self.email_to: personalization.add_to(Email(self.email_to)) for recipient in self.recipient_ids: personalization.add_to(Email(recipient.email)) if self.email_cc: personalization.add_cc(Email(self.email_cc)) else: _logger.info('Sending email to test address {}'.format( test_address)) personalization.add_to(Email(test_address)) self.email_to = test_address if self.sendgrid_template_id: s_mail.set_template_id(self.sendgrid_template_id.remote_id) for substitution in self.substitution_ids: personalization.add_substitution(Substitution( substitution.key, substitution.value)) s_mail.add_personalization(personalization) for attachment in self.attachment_ids: s_attachment = Attachment() # Datas are not encoded properly for sendgrid s_attachment.set_content(base64.b64encode(base64.b64decode( attachment.datas))) s_attachment.set_filename(attachment.name) s_mail.add_attachment(s_attachment) return s_mail.get()
def send(self, sender, subject, message, recipients=None, message_type="text/plain", api_key=None, attachments=None): """ @param sender:string (the sender of the email) @param recipient:list (list of recipients of the email) @param subject:string (subject of the email) @param message:string (content of the email) @param message_type:string (mime type of the email content) @param api_key:string (the api key of sendgrid) @param attachments:list (list of Attachment tuple) """ api_key = api_key or os.environ.get("SENDGRID_API_KEY", None) if recipients is None or recipients == []: return if attachments is None: attachments = [] if api_key is None: raise RuntimeError( "Make sure to export SENDGRID_API_KEY or pass your api key") sg = sendgrid.SendGridAPIClient(apikey=api_key) from_email = Email(sender) to_email = Email(recipients[0]) content = Content(message_type, message) mail = Mail(from_email, subject, to_email, content) to = list(set(recipients)) # no duplicates. if len(to) > 1: for receiver in to[1:]: mail.personalizations[0].add_to(Email(receiver)) for attachment in attachments: mail.add_attachment(self.build_attachment(attachment)) try: response = sg.client.mail.send.post(request_body=mail.get()) except Exception as e: self._log_info(e) raise e self._log_info("Email sent..") return response.status_code, response.body
def send_email(receivers, subject, content, template_id=None, text_replacements=None, sender_name=None, sender_email=None, attachments=None, cc_list=None, bcc_list=None): print(os.environ.get('SENDGRID_API_KEY'), ' is the sendgrid api key') sendgrid_client = sendgrid.SendGridAPIClient( api_key=os.environ.get('SENDGRID_API_KEY')) sender = sendgrid.Email(name=sender_name, email=sender_email) mail = Mail(from_email=sender, subject=subject, content=content) personalization = Personalization() if len(receivers) == 0: error = Error({'detail': 'Please enter receiver mailId'}, status=status.HTTP_400_BAD_REQUEST) return error, None else: for receiver in receivers: personalization.add_to(receiver) personalization.add_to(receivers[0]) for cc in cc_list and cc_list is not None: personalization.add_cc(cc) for bcc in bcc_list and bcc_list is not None: personalization.add_bcc(bcc) mail.add_personalization(personalization) if text_replacements is not None: for text_replacement in text_replacements: for key, value in text_replacement.items(): mail.personalizations[0].add_substitution( Substitution(key, value)) mail.template_id = template_id if attachments is not None: for attachment in attachments: mail.add_attachment(attachment) response = sendgrid_client.client.mail.send.post( request_body=mail.get()) return {'status': True, 'response': response.body.decode().strip()}
def send_sendgrid_email(self): self.is_sent = True user_full_name = ' '.join( [self.created_by.first_name, self.created_by.last_name]) from_email = SendGridEmail(self.created_by.email, user_full_name) subject = self.subject content = Content('text/html', self.body) contact_full_name = ' '.join([self.first_name, self.last_name]) to_email = SendGridEmail(self.to, contact_full_name) mail = Mail(from_email, subject, to_email, content) if len(self.CC) > 0: for cc in self.CC: mail.personalizations[0].add_cc(SendGridEmail(cc)) if len(self.BCC) > 0: for bcc in self.BCC: mail.personalizations[0].add_bcc(SendGridEmail(bcc)) if self.attachments.count() > 0: attachments = self.attachments.all() for file_attachment in attachments: # Content Type must exist if file_attachment.content_type != '': body = file_attachment.file.read() base_64_body = base64.b64encode(body) attachment = Attachment() attachment.content = base_64_body attachment.type = file_attachment.content_type attachment.filename = file_attachment.original_name attachment.disposition = 'attachment' attachment.content_id = file_attachment.original_name mail.add_attachment(attachment) body = mail.get() response = sg.client.mail.send.post(request_body=body) if response._headers and 'X-Message-Id' in response._headers: sendgrid_id = response._headers['X-Message-Id'] self.method = 'sendgrid' self.delivered = True self.sendgrid_id = sendgrid_id return response
def _setup_email(_notify): mail = Mail() mail.from_email = Email(**_notify.from_email) for attachment in _notify.attachment_list(): _att = Attachment() _att.content = gb64(attachment) _att.filename = os.path.split(attachment)[-1] _att.disposition = "attachment" mail.add_attachment(_att) mail.add_content(Content("text/html", _notify.message)) return mail
def send(self, sender, subject, html_content="<strong>Email</strong>", recipients=None, attachments=None): recipients = recipients or [] attachments = attachments or [] recipients = list(set(recipients)) mail = Mail(from_email=sender, to_emails=recipients, subject=subject, html_content=html_content) for at in attachments: mail.add_attachment(at) try: sg = sendgrid.SendGridAPIClient(self.apikey) # response=sg.send(mail) response = sg.client.mail.send.post(request_body=mail.get()) print(response.status_code) print(response.body) print(response.headers) except HTTPError as e: raise e
def test_kitchenSink(self): self.maxDiff = None """All settings set""" mail = Mail() mail.from_email = Email("*****@*****.**", "Example User") mail.subject = "Hello World from the SendGrid Python Library" personalization = Personalization() personalization.add_to(Email("*****@*****.**", "Example User")) personalization.add_to(Email("*****@*****.**", "Example User")) personalization.add_cc(Email("*****@*****.**", "Example User")) personalization.add_cc(Email("*****@*****.**", "Example User")) personalization.add_bcc(Email("*****@*****.**")) personalization.add_bcc(Email("*****@*****.**")) personalization.subject = "Hello World from the Personalized SendGrid Python Library" personalization.add_header(Header("X-Test", "test")) personalization.add_header(Header("X-Mock", "true")) personalization.add_substitution( Substitution("%name%", "Example User")) personalization.add_substitution(Substitution("%city%", "Denver")) personalization.add_custom_arg(CustomArg("user_id", "343")) personalization.add_custom_arg(CustomArg("type", "marketing")) personalization.send_at = 1443636843 mail.add_personalization(personalization) personalization2 = Personalization() personalization2.add_to(Email("*****@*****.**", "Example User")) personalization2.add_to(Email("*****@*****.**", "Example User")) personalization2.add_cc(Email("*****@*****.**", "Example User")) personalization2.add_cc(Email("*****@*****.**", "Example User")) personalization2.add_bcc(Email("*****@*****.**")) personalization2.add_bcc(Email("*****@*****.**")) personalization2.subject = "Hello World from the Personalized SendGrid Python Library" personalization2.add_header(Header("X-Test", "test")) personalization2.add_header(Header("X-Mock", "true")) personalization2.add_substitution( Substitution("%name%", "Example User")) personalization2.add_substitution(Substitution("%city%", "Denver")) personalization2.add_custom_arg(CustomArg("user_id", "343")) personalization2.add_custom_arg(CustomArg("type", "marketing")) personalization2.send_at = 1443636843 mail.add_personalization(personalization2) mail.add_content(Content("text/plain", "some text here")) mail.add_content( Content( "text/html", "<html><body>some text here</body></html>")) attachment = Attachment() attachment.content = "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gQ3JhcyBwdW12" attachment.type = "application/pdf" attachment.filename = "balance_001.pdf" attachment.disposition = "attachment" attachment.content_id = "Balance Sheet" mail.add_attachment(attachment) attachment2 = Attachment() attachment2.content = "BwdW" attachment2.type = "image/png" attachment2.filename = "banner.png" attachment2.disposition = "inline" attachment2.content_id = "Banner" mail.add_attachment(attachment2) mail.template_id = "13b8f94f-bcae-4ec6-b752-70d6cb59f932" mail.add_section( Section( "%section1%", "Substitution Text for Section 1")) mail.add_section( Section( "%section2%", "Substitution Text for Section 2")) mail.add_header(Header("X-Test1", "test1")) mail.add_header(Header("X-Test3", "test2")) mail.add_header({"X-Test4": "test4"}) mail.add_category(Category("May")) mail.add_category(Category("2016")) mail.add_custom_arg(CustomArg("campaign", "welcome")) mail.add_custom_arg(CustomArg("weekday", "morning")) mail.send_at = 1443636842 mail.batch_id = "sendgrid_batch_id" mail.asm = ASM(99, [4, 5, 6, 7, 8]) mail.ip_pool_name = "24" mail_settings = MailSettings() mail_settings.bcc_settings = BCCSettings( True, Email("*****@*****.**")) mail_settings.bypass_list_management = BypassListManagement(True) mail_settings.footer_settings = FooterSettings( True, "Footer Text", "<html><body>Footer Text</body></html>") mail_settings.sandbox_mode = SandBoxMode(True) mail_settings.spam_check = SpamCheck( True, 1, "https://spamcatcher.sendgrid.com") mail.mail_settings = mail_settings tracking_settings = TrackingSettings() tracking_settings.click_tracking = ClickTracking( True, True) tracking_settings.open_tracking = OpenTracking( True, "Optional tag to replace with the open image in the body of the message") tracking_settings.subscription_tracking = SubscriptionTracking( True, "text to insert into the text/plain portion of the message", "<html><body>html to insert into the text/html portion of the message</body></html>", "Optional tag to replace with the open image in the body of the message") tracking_settings.ganalytics = Ganalytics( True, "some source", "some medium", "some term", "some content", "some campaign") mail.tracking_settings = tracking_settings mail.reply_to = Email("*****@*****.**") expected_result = { "asm": { "group_id": 99, "groups_to_display": [4, 5, 6, 7, 8] }, "attachments": [ { "content": "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3" "RldHVyIGFkaXBpc2NpbmcgZWxpdC4gQ3JhcyBwdW12", "content_id": "Balance Sheet", "disposition": "attachment", "filename": "balance_001.pdf", "type": "application/pdf" }, { "content": "BwdW", "content_id": "Banner", "disposition": "inline", "filename": "banner.png", "type": "image/png" } ], "batch_id": "sendgrid_batch_id", "categories": [ "May", "2016" ], "content": [ { "type": "text/plain", "value": "some text here" }, { "type": "text/html", "value": "<html><body>some text here</body></html>" } ], "custom_args": { "campaign": "welcome", "weekday": "morning" }, "from": { "email": "*****@*****.**", "name": "Example User" }, "headers": { "X-Test1": "test1", "X-Test3": "test2", "X-Test4": "test4" }, "ip_pool_name": "24", "mail_settings": { "bcc": { "email": "*****@*****.**", "enable": True }, "bypass_list_management": { "enable": True }, "footer": { "enable": True, "html": "<html><body>Footer Text</body></html>", "text": "Footer Text" }, "sandbox_mode": { "enable": True }, "spam_check": { "enable": True, "post_to_url": "https://spamcatcher.sendgrid.com", "threshold": 1 } }, "personalizations": [ { "bcc": [ { "email": "*****@*****.**" }, { "email": "*****@*****.**" } ], "cc": [ { "email": "*****@*****.**", "name": "Example User" }, { "email": "*****@*****.**", "name": "Example User" } ], "custom_args": { "type": "marketing", "user_id": "343" }, "headers": { "X-Mock": "true", "X-Test": "test" }, "send_at": 1443636843, "subject": "Hello World from the Personalized SendGrid " "Python Library", "substitutions": { "%city%": "Denver", "%name%": "Example User" }, "to": [ { "email": "*****@*****.**", "name": "Example User" }, { "email": "*****@*****.**", "name": "Example User" } ] }, { "bcc": [ { "email": "*****@*****.**" }, { "email": "*****@*****.**" } ], "cc": [ { "email": "*****@*****.**", "name": "Example User" }, { "email": "*****@*****.**", "name": "Example User" } ], "custom_args": { "type": "marketing", "user_id": "343" }, "headers": { "X-Mock": "true", "X-Test": "test" }, "send_at": 1443636843, "subject": "Hello World from the Personalized SendGrid " "Python Library", "substitutions": { "%city%": "Denver", "%name%": "Example User" }, "to": [ { "email": "*****@*****.**", "name": "Example User" }, { "email": "*****@*****.**", "name": "Example User" } ] } ], "reply_to": { "email": "*****@*****.**" }, "sections": { "%section1%": "Substitution Text for Section 1", "%section2%": "Substitution Text for Section 2" }, "send_at": 1443636842, "subject": "Hello World from the SendGrid Python Library", "template_id": "13b8f94f-bcae-4ec6-b752-70d6cb59f932", "tracking_settings": { "click_tracking": { "enable": True, "enable_text": True }, "ganalytics": { "enable": True, "utm_campaign": "some campaign", "utm_content": "some content", "utm_medium": "some medium", "utm_source": "some source", "utm_term": "some term" }, "open_tracking": { "enable": True, "substitution_tag": "Optional tag to replace with the " "open image in the body of the message" }, "subscription_tracking": { "enable": True, "html": "<html><body>html to insert into the text/html " "portion of the message</body></html>", "substitution_tag": "Optional tag to replace with the open" " image in the body of the message", "text": "text to insert into the text/plain portion of" " the message" } } } self.assertEqual( json.dumps(mail.get(), sort_keys=True), json.dumps(expected_result, sort_keys=True) )
def _build_sg_mail(self, msg): mail = Mail() mail.from_email = Email(*self._parse_email_address(msg.from_email)) mail.subject = msg.subject personalization = Personalization() for addr in msg.to: personalization.add_to(Email(*self._parse_email_address(addr))) for addr in msg.cc: personalization.add_cc(Email(*self._parse_email_address(addr))) for addr in msg.bcc: personalization.add_bcc(Email(*self._parse_email_address(addr))) personalization.subject = msg.subject for k, v in msg.extra_headers.items(): if k.lower() == "reply-to": mail.reply_to = Email(v) else: personalization.add_header(Header(k, v)) if hasattr(msg, "template_id"): mail.template_id = msg.template_id if hasattr(msg, "substitutions"): for k, v in msg.substitutions.items(): personalization.add_substitution(Substitution(k, v)) # write through the ip_pool_name attribute if hasattr(msg, "ip_pool_name"): if not isinstance(msg.ip_pool_name, basestring): raise ValueError( "ip_pool_name must be a string, got: {}; " "see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/" "index.html#-Request-Body-Parameters".format( type(msg.ip_pool_name))) if not 2 <= len(msg.ip_pool_name) <= 64: raise ValueError( "the number of characters of ip_pool_name must be min 2 and max 64, got: {}; " "see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/" "index.html#-Request-Body-Parameters".format( len(msg.ip_pool_name))) mail.ip_pool_name = msg.ip_pool_name # write through the send_at attribute if hasattr(msg, "send_at"): if not isinstance(msg.send_at, int): raise ValueError( "send_at must be an integer, got: {}; " "see https://sendgrid.com/docs/API_Reference/SMTP_API/scheduling_parameters.html#-Send-At".format( type(msg.send_at))) personalization.send_at = msg.send_at mail.add_personalization(personalization) if hasattr(msg, "reply_to") and msg.reply_to: if mail.reply_to: # If this code path is triggered, the reply_to on the sg mail was set in a header above reply_to = Email(*self._parse_email_address(msg.reply_to)) if reply_to.email != mail.reply_to.email or reply_to.name != mail.reply_to.name: raise ValueError("Sendgrid only allows 1 email in the reply-to field. " + "Reply-To header value != reply_to property value.") if not isinstance(msg.reply_to, basestring): if len(msg.reply_to) > 1: raise ValueError("Sendgrid only allows 1 email in the reply-to field") mail.reply_to = Email(*self._parse_email_address(msg.reply_to[0])) else: mail.reply_to = Email(*self._parse_email_address(msg.reply_to)) for attch in msg.attachments: attachment = Attachment() if isinstance(attch, MIMEBase): filename = attch.get_filename() if not filename: ext = mimetypes.guess_extension(attch.get_content_type()) filename = "part-{0}{1}".format(uuid.uuid4().hex, ext) attachment.filename = filename # todo: Read content if stream? attachment.content = attch.get_payload().replace("\n", "") attachment.type = attch.get_content_type() content_id = attch.get("Content-ID") if content_id: # Strip brackets since sendgrid's api adds them if content_id.startswith("<") and content_id.endswith(">"): content_id = content_id[1:-1] attachment.content_id = content_id attachment.disposition = "inline" else: filename, content, mimetype = attch attachment.filename = filename # Convert content from chars to bytes, in both Python 2 and 3. # todo: Read content if stream? if isinstance(content, str): content = content.encode('utf-8') attachment.content = base64.b64encode(content).decode() attachment.type = mimetype mail.add_attachment(attachment) msg.body = ' ' if msg.body == '' else msg.body if isinstance(msg, EmailMultiAlternatives): mail.add_content(Content("text/plain", msg.body)) for alt in msg.alternatives: if alt[1] == "text/html": mail.add_content(Content(alt[1], alt[0])) elif msg.content_subtype == "html": mail.add_content(Content("text/plain", " ")) mail.add_content(Content("text/html", msg.body)) else: mail.add_content(Content("text/plain", msg.body)) if hasattr(msg, "categories"): for cat in msg.categories: mail.add_category(Category(cat)) if hasattr(msg, "asm"): if "group_id" not in msg.asm: raise KeyError("group_id not found in asm") if "groups_to_display" in msg.asm: mail.asm = ASM(msg.asm["group_id"], msg.asm["groups_to_display"]) else: mail.asm = ASM(msg.asm["group_id"]) mail_settings = MailSettings() mail_settings.sandbox_mode = SandBoxMode(self.sandbox_mode) mail.mail_settings = mail_settings tracking_settings = TrackingSettings() tracking_settings.open_tracking = OpenTracking(self.track_email) mail.tracking_settings = tracking_settings return mail.get()
def send_email(to, subject, html_content, files=None, dryrun=False, cc=None, bcc=None, mime_subtype='mixed', sandbox_mode=False, **kwargs): """ Send an email with html content using sendgrid. To use this plugin: 0. include sendgrid subpackage as part of your Airflow installation, e.g., pip install 'apache-airflow[sendgrid]' 1. update [email] backend in airflow.cfg, i.e., [email] email_backend = airflow.contrib.utils.sendgrid.send_email 2. configure Sendgrid specific environment variables at all Airflow instances: SENDGRID_MAIL_FROM={your-mail-from} SENDGRID_API_KEY={your-sendgrid-api-key}. """ if files is None: files = [] mail = Mail() from_email = kwargs.get('from_email') or os.environ.get('SENDGRID_MAIL_FROM') from_name = kwargs.get('from_name') or os.environ.get('SENDGRID_MAIL_SENDER') mail.from_email = Email(from_email, from_name) mail.subject = subject mail.mail_settings = MailSettings() if sandbox_mode: mail.mail_settings.sandbox_mode = SandBoxMode(enable=True) # Add the recipient list of to emails. personalization = Personalization() to = get_email_address_list(to) for to_address in to: personalization.add_to(Email(to_address)) if cc: cc = get_email_address_list(cc) for cc_address in cc: personalization.add_cc(Email(cc_address)) if bcc: bcc = get_email_address_list(bcc) for bcc_address in bcc: personalization.add_bcc(Email(bcc_address)) # Add custom_args to personalization if present pers_custom_args = kwargs.get('personalization_custom_args', None) if isinstance(pers_custom_args, dict): for key in pers_custom_args.keys(): personalization.add_custom_arg(CustomArg(key, pers_custom_args[key])) mail.add_personalization(personalization) mail.add_content(Content('text/html', html_content)) categories = kwargs.get('categories', []) for cat in categories: mail.add_category(Category(cat)) # Add email attachment. for fname in files: basename = os.path.basename(fname) attachment = Attachment() attachment.type = mimetypes.guess_type(basename)[0] attachment.filename = basename attachment.disposition = "attachment" attachment.content_id = '<{0}>'.format(basename) with open(fname, "rb") as f: attachment.content = base64.b64encode(f.read()).decode('utf-8') mail.add_attachment(attachment) _post_sendgrid_mail(mail.get())
def _build_sg_mail(self, email): mail = Mail() from_name, from_email = rfc822.parseaddr(email.from_email) # Python sendgrid client should improve # sendgrid/helpers/mail/mail.py:164 if not from_name: from_name = None mail.set_from(Email(from_email, from_name)) mail.set_subject(email.subject) personalization = Personalization() for e in email.to: personalization.add_to(Email(e)) for e in email.cc: personalization.add_cc(Email(e)) for e in email.bcc: personalization.add_bcc(Email(e)) personalization.set_subject(email.subject) mail.add_content(Content("text/plain", email.body)) if isinstance(email, EmailMultiAlternatives): for alt in email.alternatives: if alt[1] == "text/html": mail.add_content(Content(alt[1], alt[0])) elif email.content_subtype == "html": mail.contents = [] mail.add_content(Content("text/plain", ' ')) mail.add_content(Content("text/html", email.body)) if hasattr(email, 'categories'): for c in email.categories: mail.add_category(Category(c)) if hasattr(email, 'custom_args'): for k, v in email.custom_args.items(): mail.add_custom_arg(CustomArg(k, v)) if hasattr(email, 'template_id'): mail.set_template_id(email.template_id) if hasattr(email, 'substitutions'): for key, value in email.substitutions.items(): personalization.add_substitution(Substitution(key, value)) # SendGrid does not support adding Reply-To as an extra # header, so it needs to be manually removed if it exists. reply_to_string = "" for key, value in email.extra_headers.items(): if key.lower() == "reply-to": reply_to_string = value else: mail.add_header({key: value}) # Note that if you set a "Reply-To" header *and* the reply_to # attribute, the header's value will be used. if not mail.reply_to and hasattr(email, "reply_to") and email.reply_to: # SendGrid only supports setting Reply-To to a single address. # See https://github.com/sendgrid/sendgrid-csharp/issues/339. reply_to_string = email.reply_to[0] # Determine whether reply_to contains a name and email address, or # just an email address. if reply_to_string: reply_to_name, reply_to_email = rfc822.parseaddr(reply_to_string) if reply_to_name and reply_to_email: mail.set_reply_to(Email(reply_to_email, reply_to_name)) elif reply_to_email: mail.set_reply_to(Email(reply_to_email)) for attachment in email.attachments: if isinstance(attachment, MIMEBase): attach = Attachment() attach.set_filename(attachment.get_filename()) attach.set_content(base64.b64encode(attachment.get_payload())) mail.add_attachment(attach) elif isinstance(attachment, tuple): attach = Attachment() attach.set_filename(attachment[0]) base64_attachment = base64.b64encode(attachment[1]) if sys.version_info >= (3,): attach.set_content(str(base64_attachment, 'utf-8')) else: attach.set_content(base64_attachment) attach.set_type(attachment[2]) mail.add_attachment(attach) mail.add_personalization(personalization) return mail.get()