def formataddr(pair, charset='utf-8'): """The inverse of parseaddr(), this takes a 2-tuple of the form (realname, email_address) and returns the string value suitable for an RFC 2822 From, To or Cc header. If the first element of pair is false, then the second element is returned unmodified. Optional charset if given is the character set that is used to encode realname in case realname is not ASCII safe. Can be an instance of str or a Charset-like object which has a header_encode method. Default is 'utf-8'. """ name, address = pair # The address MUST (per RFC) be ascii, so throw a UnicodeError if it isn't. address.encode('ascii') if name: try: name.encode('ascii') except UnicodeEncodeError: if isinstance(charset, str): charset = Charset(charset) encoded_name = charset.header_encode(name) return "%s <%s>" % (encoded_name, address) else: quotes = '' if specialsre.search(name): quotes = '"' name = escapesre.sub(r'\\\g<0>', name) return '%s%s%s <%s>' % (quotes, name, quotes, address) return address
def format(self, events, encoding="utf-8"): parts = list() data = templates.Template.format(self, parts, events) parsed = message_from_string(data.encode(encoding)) charset = Charset(encoding) charset.header_encoding = QP msg = MIMEMultipart() msg.set_charset(charset) for key, value in msg.items(): del parsed[key] for key, value in parsed.items(): msg[key] = value for encoded in ["Subject", "Comment"]: if encoded not in msg: continue value = charset.header_encode(msg[encoded]) del msg[encoded] msg[encoded] = value del msg["Content-Transfer-Encoding"] msg["Content-Transfer-Encoding"] = "7bit" msg.attach(MIMEText(parsed.get_payload(), "plain", encoding)) for part in parts: msg.attach(part) return msg
def formataddr(pair, charset='utf-8'): """The inverse of parseaddr(), this takes a 2-tuple of the form (realname, email_address) and returns the string value suitable for an RFC 2822 From, To or Cc header. If the first element of pair is false, then the second element is returned unmodified. Optional charset if given is the character set that is used to encode realname in case realname is not ASCII safe. Can be an instance of str or a Charset-like object which has a header_encode method. Default is 'utf-8'. """ name, address = pair # The address MUST (per RFC) be ascii, so raise a UnicodeError if it isn't. address.encode('ascii') if name: try: name.encode('ascii') except UnicodeEncodeError: if isinstance(charset, str): charset = Charset(charset) encoded_name = charset.header_encode(name) return "%s <%s>" % (encoded_name, address) else: quotes = '' if specialsre.search(name): quotes = '"' name = escapesre.sub(r'\\\g<0>', name) return '%s%s%s <%s>' % (quotes, name, quotes, address) return address
def format(self, events, encoding="utf-8"): parts = list() data = templates.Template.format(self, parts, events) parsed = message_from_string(data.encode(encoding)) charset = Charset(encoding) charset.header_encoding = QP msg = MIMEMultipart() msg.set_charset(charset) for key, value in msg.items(): del parsed[key] for key, value in parsed.items(): msg[key] = value for encoded in ["Subject", "Comment"]: if encoded not in msg: continue value = charset.header_encode(msg[encoded]) del msg[encoded] msg[encoded] = value del msg['Content-Transfer-Encoding'] msg['Content-Transfer-Encoding'] = '7bit' msg.attach(MIMEText(parsed.get_payload(), "plain", encoding)) for part in parts: msg.attach(part) return msg
def format(self, events, encoding="utf-8"): from email import message_from_string from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.charset import Charset, QP from email.utils import formatdate, make_msgid parts = list() data = templates.Template.format(self, parts, events) parsed = message_from_string(data.encode(encoding)) charset = Charset(encoding) charset.header_encoding = QP msg = MIMEMultipart() msg.set_charset(charset) for key, value in msg.items(): del parsed[key] for key, value in parsed.items(): msg[key] = value for encoded in ["Subject", "Comment"]: if encoded not in msg: continue value = charset.header_encode(msg[encoded]) del msg[encoded] msg[encoded] = value del msg['Content-Transfer-Encoding'] msg['Content-Transfer-Encoding'] = '7bit' msg.attach(MIMEText(parsed.get_payload(), "plain", encoding)) for part in parts: msg.attach(part) return msg
def send(self, subject, recipients, sender=None, attach=None, html=None, text=None, template=None, **kwargs): """ Отправка самосборного письма. Ссылки на картинке в статике превращаются в аттачменты. Текст правильно кодируется, чтобы избежать багов с переносом строки в Flask-Mail recipients - список attach - вложения, словарь имя-путь template - можно указать имя шаблона без расширения """ sender = sender or self.default_sender if template: html, text = render_email(template, **kwargs) recipients_str = self._contact_list(recipients) charset = Charset(input_charset='utf-8') msgRoot = MIMEMultipart('related') msgRoot['Subject'] = charset.header_encode(subject) msgRoot['From'] = self._contact(sender) msgRoot['To'] = recipients_str msgRoot.preamble = 'This is a multi-part message in MIME format.' msgRoot.set_charset('utf-8') msgAlternative = MIMEMultipart(_subtype='alternative') msgAlternative.set_charset("utf-8") msgRoot.attach(msgAlternative) msgText = MIMEText(_text=text, _subtype='plain', _charset='utf-8') msgAlternative.attach(msgText) html, images = self._extract_statics(html) self._attach_images(msgRoot, images) if attach: self._attach_images(msgRoot, attach) msgHtml = MIMEText(_text=html, _subtype='html', _charset='utf-8') msgAlternative.attach(msgHtml) if self.mail_enabled: with smtplib.SMTP(host=self.mail_server, port=self.mail_port) as smtp: smtp.sendmail( self._address(sender), [self._address(r) for r in recipients], msgRoot.as_string() )
def formataddr(pair, charset='utf-8'): (name, address) = pair address.encode('ascii') if name: try: name.encode('ascii') except UnicodeEncodeError: if isinstance(charset, str): charset = Charset(charset) encoded_name = charset.header_encode(name) return '%s <%s>' % (encoded_name, address) quotes = '' if specialsre.search(name): quotes = '"' name = escapesre.sub('\\\\\\g<0>', name) return '%s%s%s <%s>' % (quotes, name, quotes, address) return address
def encode_address(addr): name, email = parseaddr(addr) charset = Charset(guess_charset(name)) encoded_name = charset.header_encode(name) return formataddr((encoded_name, email))
def send_email(subject, recipients, sender=None, attach=None, html_body=None, text_body=None, template=None, **kwargs): """ Отправка самосборного письма. Ссылки на картинке в статике превращаются в аттачменты. Текст правильно кодируется, чтобы избежать багов с переносом строки в Flask-Mail recipients - Список attach - Вложения, словарь имя-путь template - Имя шаблона без расширения. Будет искатся пара файлов <template>.html и <template>.txt """ if sender is None: cfg = current_app.config sender = cfg.get('MAIL_DEFAULT_SENDER', 'no-reply@{}'.format(cfg.get('SERVER_NAME', 'example.com'))) if template: html_body, text_body = render_email(template, **kwargs) recipients_str = contact_list(recipients) charset = Charset(input_charset='utf-8') msgRoot = MIMEMultipart('related') msgRoot['Subject'] = charset.header_encode(subject) msgRoot['From'] = contact(sender) msgRoot['To'] = recipients_str msgRoot.preamble = 'This is a multi-part message in MIME format.' msgRoot.set_charset('utf-8') msgAlternative = MIMEMultipart(_subtype='alternative') msgAlternative.set_charset("utf-8") msgRoot.attach(msgAlternative) msgText = MIMEText(_text=text_body, _subtype='plain', _charset='utf-8') msgAlternative.attach(msgText) html, images = extract_statics(html_body) attach_images(msgRoot, images) if attach: attach_images(msgRoot, attach) msgHtml = MIMEText(_text=html, _subtype='html', _charset='utf-8') msgAlternative.attach(msgHtml) if current_app.config['MAIL_ENABLED']: with smtplib.SMTP( host=current_app.config['MAIL_SERVER'], port=current_app.config['MAIL_PORT']) as smtp: try: smtp.sendmail( address(sender), [address(r) for r in recipients], msgRoot.as_string() ) if current_app.config.get('DEBUG'): print('=== MAIL FROM "%s" TO "%s"' % (address(sender), repr([address(r) for r in recipients]))) print(msgRoot.as_string()) except smtplib.SMTPRecipientsRefused: print('smtplib.SMTPRecipientsRefused: %s' % repr(recipients))