def __init__(self, m, to, sender, subject=None, cc=None, bcc=None): super().__init__() self.m = check_m(m) to = to_list(to) cc = to_list(cc) bcc = to_list(bcc) if not subject: subject = '%s mailer' % (IDENT) subject = '%s - %s' % (subject, get_timestamp()) self.__sender = sender self.__recipients = list(_chain(to, cc, bcc)) _charset.add_charset('utf-8', _charset.QP, _charset.QP, 'UTF-8') self.__message = _MIMEMultipart() self.__message.add_header('To', ', '.join(to)) if cc: self.__message.add_header('CC', ', '.join(cc)) self.__message.add_header('From', sender) self.__message.add_header('Subject', subject) self.__message.add_header('Date', _formatdate()) self.__message.add_header('X-Mailer', '%s mailer' % (IDENT)) self.m('mail tool startup done', more=dict(to=to, cc=cc, bcc=bcc, sender=sender, subject=subject), verbose=False)
def encrypt(message, recipients, gpg, **kwargs): r"""Encrypt a ``Message``, returning the encrypted version. using gpg.encrypt() others, mostly, taken from W. T. King """ flattenedMsg = _flatten(message) eResult = gpg.encrypt(flattenedMsg, recipients, **kwargs) assert eResult.ok == True, (recipients, kwargs) encrypted = eResult.data enc = _MIMEApplication( _data=encrypted, _subtype='octet-stream; name="encrypted.asc"', _encoder=_encode_7or8bit) enc['Content-Description'] = 'OpenPGP encrypted message' enc.set_charset('us-ascii') control = _MIMEApplication( _data='Version: 1\n', _subtype='pgp-encrypted', _encoder=_encode_7or8bit) control.set_charset('us-ascii') msg = _MIMEMultipart( 'encrypted', micalg='pgp-sha1', protocol='application/pgp-encrypted') msg.attach(control) msg.attach(enc) msg['Content-Disposition'] = 'inline' return msg
def __init__(self, m, to, sender, subject=None, cc=None, bcc=None): super().__init__() self.m = check_m(m) to = to_list(to) cc = to_list(cc) bcc = to_list(bcc) if not subject: subject = '%s mailer' % (IDENT) subject = '%s - %s' % (subject, get_timestamp()) self.__sender = sender self.__recipients = list(_chain(to, cc, bcc)) _charset.add_charset('utf-8', _charset.QP, _charset.QP, 'UTF-8') self.__message = _MIMEMultipart() self.__message.add_header('To', ', '.join(to)) if cc: self.__message.add_header('CC', ', '.join(cc)) self.__message.add_header('From', sender) self.__message.add_header('Subject', subject) self.__message.add_header('Date', _formatdate()) self.__message.add_header('X-Mailer', '%s mailer' % (IDENT)) self.m( 'mail tool startup done', more=dict(to=to, cc=cc, bcc=bcc, sender=sender, subject=subject), verbose=False )
def sign(message, gpg, **kwargs): r"""Sign a ``Message``, returning the signed version. using gpg.sign() others, mostly, taken from W. T. King """ # should use replace, otherwise it does NOT work # READ ---- page 5 of RFC 3156 flattenedMsg = _flatten(message).replace('\n', '\r\n') assert kwargs signature = str( gpg.sign(flattenedMsg, detach=True, **kwargs) ) assert signature sig = _MIMEApplication( _data=signature, _subtype='pgp-signature; name="signature.asc"', _encoder=_encode_7or8bit) sig['Content-Description'] = 'OpenPGP digital signature' sig.set_charset('us-ascii') msg = _MIMEMultipart( 'signed', micalg='pgp-sha1', protocol='application/pgp-signature') msg.attach(message) msg.attach(sig) msg['Content-Disposition'] = 'inline' return msg
def _new_digest(self): digest = _MIMEMultipart('digest') digest['To'] = self.to # TODO: _Header(), _formataddr((recipient_name, recipient_addr)) digest['Subject'] = 'digest for {}'.format(self.name) digest['Message-ID'] = '<{}@dev.null.invalid>'.format(_uuid.uuid4()) digest['User-Agent'] = self.user_agent digest['X-RSS-Feed'] = self.url return digest
def _new_digest(self): digest = _MIMEMultipart('digest') digest['To'] = self.to # TODO: _Header(), _formataddr((recipient_name, recipient_addr)) digest['Subject'] = 'digest for {}'.format(self.name) digest['Message-ID'] = '<{}@dev.null.invalid>'.format(_uuid.uuid4()) digest['User-Agent'] = _USER_AGENT digest['X-RSS-Feed'] = self.url return digest
def _get_mine_message(self): ''' generate MIMEText or MIMEMultipart objects ''' if self._attachments: return _MIMEMultipart('related') elif self.html: #return _MIMEMultipart('alternative') return _MIMEText(self.html, 'html', self.encoding) return _MIMEText(self.text, 'plain', self.encoding)
def _new_digest(self): digest = _MIMEMultipart('digest') digest['To'] = _formataddr(_parseaddr(self.to)) # Encodes with utf-8 as necessary digest['Subject'] = 'digest for {}'.format(self.name) digest['Message-ID'] = '<{0}@{1}>'.format(_uuid.uuid4(), platform.node()) digest['User-Agent'] = self.user_agent digest['List-ID'] = '<{}.localhost>'.format(self.name) digest['List-Post'] = 'NO (posting not allowed on this list)' digest['X-RSS-Feed'] = self.url return digest
def _new_digest(self): digest = _MIMEMultipart('digest') digest[ 'To'] = self.to # TODO: _Header(), _formataddr((recipient_name, recipient_addr)) digest['Subject'] = 'digest for {}'.format(self.name) digest['Message-ID'] = '<{0}@{1}>'.format(_uuid.uuid4(), platform.node()) digest['User-Agent'] = self.user_agent digest['List-ID'] = '<{}.localhost>'.format(self.name) digest['List-Post'] = 'NO (posting not allowed on this list)' digest['X-RSS-Feed'] = self.url return digest
def construct_response(author, targets, subject, text, original, cc=None): r"""Build a multipart/mixed response email using `Person` instances >>> from pygrader.model.person import Person as Person >>> student = Person(name='Джон Доу', emails=['*****@*****.**']) >>> assistant = Person(name='Jill', emails=['*****@*****.**']) >>> cc = [assistant] >>> msg = construct_text_email(author=student, targets=[assistant], ... subject='Assignment 1 submission', text='Bla bla bla...') >>> rsp = construct_response(author=assistant, targets=[student], ... subject='Received assignment 1 submission', text='3 hours late', ... original=msg) >>> print(rsp.as_string()) # doctest: +REPORT_UDIFF, +ELLIPSIS Content-Type: multipart/mixed; boundary="===============...==" MIME-Version: 1.0 Date: ... From: Jill <*****@*****.**> Reply-to: Jill <*****@*****.**> To: =?utf-8?b?0JTQttC+0L0g0JTQvtGD?= <*****@*****.**> Subject: Received assignment 1 submission <BLANKLINE> --===============...== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline <BLANKLINE> 3 hours late --===============...== Content-Type: message/rfc822 MIME-Version: 1.0 <BLANKLINE> Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline Date: ... From: =?utf-8?b?0JTQttC+0L0g0JTQvtGD?= <*****@*****.**> Reply-to: =?utf-8?b?0JTQttC+0L0g0JTQvtGD?= <*****@*****.**> To: Jill <*****@*****.**> Subject: Assignment 1 submission <BLANKLINE> Bla bla bla... --===============...==-- """ message = _MIMEMultipart('mixed') message.attach(_pgp_mime.encodedMIMEText(text)) message.attach(_MIMEMessage(original)) return construct_email( author=author, targets=targets, subject=subject, message=message, cc=cc)
def as_string(self): ''' encode email message as string ''' msg = self._get_mine_message() # set message header msg['From'] = self._header(self.sender) msg['To'] = self._header(self.recp) msg['Subject'] = self._header(self.subject) if self.importance != None: msg['Importance'] = self.importance msg['Date'] = time.ctime() # attach message body if msg.is_multipart(): # attach multiple parts if required part = _MIMEMultipart('alternative') self._attach_text(part, inline=True) self._attach_html(part, inline=True) msg.attach(part) # attach attachments self._attach_files(msg) return msg.as_string()
def _get_student_submission_email(basedir, course, person, assignments, student): _LOG.debug('construct student submission email about {} {} for {}'.format( student, assignments, person)) subject = '{} assignment submissions for {}'.format( course.name, student.name) text = '{}:\n * {}\n'.format(subject, '\n * '.join(a.name for a in assignments)) message = _MIMEMultipart('mixed') message.attach(_pgp_mime.encodedMIMEText(text)) for assignment in assignments: grade = course.grade(student=student, assignment=assignment) if grade is not None: text = '{} grade: {}\n'.format(assignment.name, grade.points) if grade.comment: text += '\n{}\n'.format(grade.comment) message.attach(_pgp_mime.encodedMIMEText(text)) assignment_path = _assignment_path(basedir, assignment, student) mpath = _os_path.join(assignment_path, 'mail') try: mbox = _mailbox.Maildir(mpath, factory=None, create=False) except _mailbox.NoSuchMailboxError as e: pass else: messages = [] for key, msg in mbox.items(): subpath = mbox._lookup(key) if subpath.endswith('.gitignore'): _LOG.debug('skipping non-message {}'.format(subpath)) continue messages.append(msg) messages.sort(key=_message_time) for msg in messages: message.attach(_MIMEMessage(msg)) return _construct_email(author=course.robot, targets=[person], subject=subject, message=message)
def _get_student_submission_email( basedir, course, person, assignments, student): _LOG.debug('construct student submission email about {} {} for {}'.format( student, assignments, person)) subject = '{} assignment submissions for {}'.format( course.name, student.name) text = '{}:\n * {}\n'.format( subject, '\n * '.join(a.name for a in assignments)) message = _MIMEMultipart('mixed') message.attach(_pgp_mime.encodedMIMEText(text)) for assignment in assignments: grade = course.grade(student=student, assignment=assignment) if grade is not None: text = '{} grade: {}\n'.format(assignment.name, grade.points) if grade.comment: text += '\n{}\n'.format(grade.comment) message.attach(_pgp_mime.encodedMIMEText(text)) assignment_path = _assignment_path(basedir, assignment, student) mpath = _os_path.join(assignment_path, 'mail') try: mbox = _mailbox.Maildir(mpath, factory=None, create=False) except _mailbox.NoSuchMailboxError as e: pass else: messages = [] for key,msg in mbox.items(): subpath = mbox._lookup(key) if subpath.endswith('.gitignore'): _LOG.debug('skipping non-message {}'.format(subpath)) continue messages.append(msg) messages.sort(key=_message_time) for msg in messages: message.attach(_MIMEMessage(msg)) return _construct_email( author=course.robot, targets=[person], subject=subject, message=message)
def sign(message, **kwargs): r"""Sign a ``Message``, returning the signed version. multipart/signed +-> text/plain (body) +-> application/pgp-signature (signature) >>> from pgp_mime.email import encodedMIMEText >>> message = encodedMIMEText('Hi\nBye') >>> signed = sign(message, signers=['*****@*****.**']) >>> signed.set_boundary('boundsep') >>> print(signed.as_string().replace( ... 'micalg="pgp-sha1"; protocol="application/pgp-signature"', ... 'protocol="application/pgp-signature"; micalg="pgp-sha1"')) ... # doctest: +ELLIPSIS, +REPORT_UDIFF Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg="pgp-sha1"; boundary="boundsep" MIME-Version: 1.0 Content-Disposition: inline <BLANKLINE> --boundsep Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline <BLANKLINE> Hi Bye --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Description: OpenPGP digital signature Content-Type: application/pgp-signature; name="signature.asc"; charset="us-ascii" <BLANKLINE> -----BEGIN PGP SIGNATURE----- Version: GnuPG... -----END PGP SIGNATURE----- <BLANKLINE> --boundsep-- >>> from email.mime.multipart import MIMEMultipart >>> message = MIMEMultipart() >>> message.attach(encodedMIMEText('Part A')) >>> message.attach(encodedMIMEText('Part B')) >>> signed = sign(message, signers=['*****@*****.**']) >>> signed.set_boundary('boundsep') >>> print(signed.as_string().replace( ... 'micalg="pgp-sha1"; protocol="application/pgp-signature"', ... 'protocol="application/pgp-signature"; micalg="pgp-sha1"')) ... # doctest: +ELLIPSIS, +REPORT_UDIFF Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg="pgp-sha1"; boundary="boundsep" MIME-Version: 1.0 Content-Disposition: inline <BLANKLINE> --boundsep Content-Type: multipart/mixed; boundary="===============...==" MIME-Version: 1.0 <BLANKLINE> --===============...== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline <BLANKLINE> Part A --===============...== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline <BLANKLINE> Part B --===============...==-- --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Description: OpenPGP digital signature Content-Type: application/pgp-signature; name="signature.asc"; charset="us-ascii" <BLANKLINE> -----BEGIN PGP SIGNATURE----- Version: GnuPG... -----END PGP SIGNATURE----- <BLANKLINE> --boundsep-- """ body = _flatten(message) signature = str(_sign_and_encrypt_bytes(data=body, **kwargs), 'us-ascii') sig = _MIMEApplication( _data=signature, _subtype='pgp-signature; name="signature.asc"', _encoder=_encode_7or8bit) sig['Content-Description'] = 'OpenPGP digital signature' sig.set_charset('us-ascii') msg = _MIMEMultipart( 'signed', micalg='pgp-sha1', protocol='application/pgp-signature') msg.attach(message) msg.attach(sig) msg['Content-Disposition'] = 'inline' return msg
parser.add_argument( '-V', '--verbose', default=0, action='count', help='increment verbosity') args = parser.parse_args() if args.verbose: _pgp_mime.LOG.setLevel(max( _logging.DEBUG, _pgp_mime.LOG.level - 10*args.verbose)) header_text = read_file(filename=args.header_file, encoding=args.encoding) header = _pgp_mime.header_from_text(header_text) body_text = read_file(filename=args.body_file, encoding=args.encoding) body = _pgp_mime.encodedMIMEText(body_text) if args.attachment: b = _MIMEMultipart() b.attach(body) body = b _mimetypes.init() for attachment in args.attachment: body.attach(load_attachment( filename=attachment, encoding=args.encoding)) config = _configparser.ConfigParser() config.read(args.config) client_params = _pgp_mime.get_client_params(config) if args.sign_as: signers = [args.sign_as] else: signers = None
default=0, action='count', help='increment verbosity') args = parser.parse_args() if args.verbose: _pgp_mime.LOG.setLevel( max(_logging.DEBUG, _pgp_mime.LOG.level - 10 * args.verbose)) header_text = read_file(filename=args.header_file, encoding=args.encoding) header = _pgp_mime.header_from_text(header_text) body_text = read_file(filename=args.body_file, encoding=args.encoding) body = _pgp_mime.encodedMIMEText(body_text) if args.attachment: b = _MIMEMultipart() b.attach(body) body = b _mimetypes.init() for attachment in args.attachment: body.attach( load_attachment(filename=attachment, encoding=args.encoding)) config = _configparser.ConfigParser() config.read(args.config) client_params = _pgp_mime.get_client_params(config) if args.sign_as: signers = [args.sign_as] else: signers = None
def embed_report(report, file_name='reporty', del_files='no', subject='', sender_name='', rec_name='', text=''): """ embeds report in custom email, and attaches html files and pngs Args: report (str): html code filename (str): name of html file (if you entered a custom file name in 'generate report', you must pass that filename through in this function) - default is 'reporty' del_files (str): 'yes' will delete files - default is 'no' (keep files) subject (str): subject of email - default is '' (no subject) sender_name (str): name of sender (will be email name no matter what on outlook) - default is '' (will result to email address on all platforms) rec_name (str): name of receiver (must be left blank for outlook users) - default is '' (will result in no send tag for gmail) text (str): any extra text you want to send will appear at start of email - default is '' (will result to no extra text) Returns: encoded multipart message """ # declaring message object message = _MIMEMultipart() # takes custom file name and adds html file extension file_name = file_name + ".html" # declaring empty file names list file_names = [] # takes filenames from if _os.path.exists("filenames.txt"): file = open("filenames.txt", "r") filenames = file.read() file.close() _os.remove("filenames.txt") file_names = filenames.strip('][').split(', ') else: pass # adds a sender_name, receiver name, and a subject if sender_name == '': pass else: message["From"] = str(sender_name) if rec_name == '': pass else: rec_name = (str(rec_name)).replace(" ", "_") message["To"] = rec_name if subject == '': pass else: message["Subject"] = str(subject) # attatches 'text' to message message.attach(_MIMEText(text, 'plain')) # attatches the html attachment to message attachment = _MIMEText(report, "html") message.attach(attachment) # adds a content id to all matplot pngs and attaches images if len(file_names) > 0: for i in range(len(file_names)): f_p = open(file_names[i], 'rb') image = _MIMEImage(f_p.read(), filename=file_names[i]) _encoders.encode_base64(image) f_p.close() image.add_header('Content-ID', '<' + file_names[i].replace('.png', '') + '>') image.add_header('Content-Disposition', 'inline', filename=file_names[i]) message.attach(image) else: pass # opens the html file and adds 'payload' attach_file = open(file_name, 'rb') payload = _MIMEBase('application', 'octate-stream') payload.set_payload(attach_file.read()) # encodes payload _encoders.encode_base64(payload) # add payload header with filename payload.add_header('Content-Disposition', 'attachment', filename=file_name) # attatches html file to the email message.attach(payload) attach_file.close() # creates final message (str) final_message = message.as_string() # deletes extra files if user specifies if del_files == 'yes': if _os.path.exists(file_name): _os.remove(file_name) else: pass for i in range(len(file_names)): if _os.path.exists(file_names[i]): _os.remove(file_names[i]) else: pass # returns the mime multipart message (str) return final_message
def send(self, receiver, cc=None, bcc=None, subject: str = None, message: str = None, image: str = None, audio: str = None, file: str = None): """ :param cc: Email Address as String or List. (Carbon Copy) :param bcc: Email Address as String or List. (Blind Carbon Copy) :param receiver: Email Address as String or List :param subject: Message Title :param message: Your Message :param image: Image File Name :param audio: Audio File Name :param file: File Name :return: Boolean """ msg = _MIMEMultipart() msg['Subject'] = subject msg['From'] = self.email try: if message is not None: text = _MIMEText(message) msg.attach(text) if image is not None: image_data = self._file_reader(image) image = _MIMEImage(_imagedata=image_data, name=image) msg.attach(image) if audio is not None: audio_data = self._file_reader(audio) audio = _MIMEAudio(_audiodata=audio_data, name=audio, _subtype='') msg.attach(audio) if file is not None: file_data = self._file_reader(file) file = _MIMEApp(_data=file_data, name=file) msg.attach(file) except Exception: print('Error: File Not Found!') self.status = False return False send_info = [] multi_info = {} if 'list' in str(type(receiver)): self.count_rec = len(receiver) receiver = ','.join(i for i in receiver) if 'list' in str(type(cc)): self.count_cc = len(cc) cc = ','.join(i for i in cc) if 'list' in str(type(bcc)): self.count_bcc = len(bcc) bcc = ','.join(i for i in bcc) if self.__login(): msg['To'] = receiver msg['CC'] = cc msg['BCC'] = bcc if self.multi: for _ in range(self.__repeat): try: self.__server.sendmail(from_addr=self.email, to_addrs=receiver, msg=msg.as_string()) except Exception: if self.__repeat == 1 & self.count_rec == 1: self.status = False else: send_info.append(False) else: if self.__repeat == 1 & self.count_rec == 1: self.status = True else: send_info.append(True) self.status = send_info finally: _sleep(self.__sleep) else: for rec in receiver.split(','): send_info = [] for _ in range(self.__repeat): try: self.__server.sendmail(from_addr=self.email, to_addrs=rec, msg=msg.as_string()) except Exception as e: if self.__repeat == 1 & self.count_rec == 1: self.status = False else: send_info.append(False) if 'OutboundSpamException' in str(e): print( 'Error: Please Login To Your Account And Verify it.' ) break else: if self.__repeat == 1 & self.count_rec == 1: self.status = True else: send_info.append(True) self.status = send_info multi_info[rec] = send_info finally: _sleep(self.__sleep) if self.count_rec != 1: self.status = multi_info self.__server.close()
smtp = _smtplib.SMTP(_settings.SMPT_HOST, _settings.SMPT_PORT) try: smtp.starttls() # enable TLS smtp.login(_settings.SMTP_USER, _settings.SMTP_PASSWORD) # Read message body: body = msg_file.read() for index, line in enumerate(csv_file): # Read names and emails: line = line.strip() if line: name, email, _ = line.split(",") # Create the container (outer) email message. outer = _MIMEMultipart() outer['Content-Type'] = 'text/plain; charset=utf-8' outer['Subject'] = encode_base64(_settings.EMAIL_SUBJECT) outer['From'] = format_named_address( _settings.EMAIL_FROM_NAME, _settings.EMAIL_FROM_ADR) outer['To'] = format_named_address(name, email) # Get source svg name: source_pdf = _path.join(_settings.DEST_GENERATED_FOLDER, f"{index}.pdf") # Set the content of the attachment: ctype, encoding = _mimetypes.guess_type(source_pdf) maintype, subtype = ctype.split('/', 1) with open(source_pdf, 'rb') as fp: msg = _MIMEImage(fp.read(), _subtype=subtype)
def sign_and_encrypt(message, signers=None, recipients=None, **kwargs): r"""Sign and encrypt a ``Message``, returning the encrypted version. multipart/encrypted +-> application/pgp-encrypted (control information) +-> application/octet-stream (body) >>> from pgp_mime.email import encodedMIMEText >>> message = encodedMIMEText('Hi\nBye') >>> message['To'] = 'pgp-mime-test <*****@*****.**>' >>> encrypted = sign_and_encrypt( ... message, signers=['*****@*****.**'], always_trust=True) >>> encrypted.set_boundary('boundsep') >>> print(encrypted.as_string().replace( ... 'micalg="pgp-sha1"; protocol="application/pgp-encrypted"', ... 'protocol="application/pgp-encrypted"; micalg="pgp-sha1"')) ... # doctest: +ELLIPSIS, +REPORT_UDIFF Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; micalg="pgp-sha1"; boundary="boundsep" MIME-Version: 1.0 Content-Disposition: inline <BLANKLINE> --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: application/pgp-encrypted; charset="us-ascii" <BLANKLINE> Version: 1 <BLANKLINE> --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Description: OpenPGP encrypted message Content-Type: application/octet-stream; name="encrypted.asc"; charset="us-ascii" <BLANKLINE> -----BEGIN PGP MESSAGE----- Version: GnuPG... -----END PGP MESSAGE----- <BLANKLINE> --boundsep-- >>> from email.mime.multipart import MIMEMultipart >>> message = MIMEMultipart() >>> message.attach(encodedMIMEText('Part A')) >>> message.attach(encodedMIMEText('Part B')) >>> encrypted = sign_and_encrypt( ... message, signers=['*****@*****.**'], ... recipients=['*****@*****.**'], always_trust=True) >>> encrypted.set_boundary('boundsep') >>> print(encrypted.as_string().replace( ... 'micalg="pgp-sha1"; protocol="application/pgp-encrypted"', ... 'protocol="application/pgp-encrypted"; micalg="pgp-sha1"')) ... # doctest: +ELLIPSIS, +REPORT_UDIFF Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; micalg="pgp-sha1"; boundary="boundsep" MIME-Version: 1.0 Content-Disposition: inline <BLANKLINE> --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: application/pgp-encrypted; charset="us-ascii" <BLANKLINE> Version: 1 <BLANKLINE> --boundsep MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Description: OpenPGP encrypted message Content-Type: application/octet-stream; name="encrypted.asc"; charset="us-ascii" <BLANKLINE> -----BEGIN PGP MESSAGE----- Version: GnuPG... -----END PGP MESSAGE----- <BLANKLINE> --boundsep-- """ _strip_bcc(message=message) body = _flatten(message) if recipients is None: recipients = [email for name,email in _email_targets(message)] _LOG.debug('extracted encryption recipients: {}'.format(recipients)) encrypted = str( _sign_and_encrypt_bytes( data=body, signers=signers, recipients=recipients, **kwargs), 'us-ascii') enc = _MIMEApplication( _data=encrypted, _subtype='octet-stream; name="encrypted.asc"', _encoder=_encode_7or8bit) enc['Content-Description'] = 'OpenPGP encrypted message' enc.set_charset('us-ascii') control = _MIMEApplication( _data='Version: 1\n', _subtype='pgp-encrypted', _encoder=_encode_7or8bit) control.set_charset('us-ascii') msg = _MIMEMultipart( 'encrypted', micalg='pgp-sha1', protocol='application/pgp-encrypted') msg.attach(control) msg.attach(enc) msg['Content-Disposition'] = 'inline' return msg