def multipart_encode(params, files, boundary=None, buf=None, sep=b'\r\n'): if buf is None: buf = [] if boundary is None: boundary = Generator._make_boundary() for(key, value) in params: b = [] b.append('--' + boundary) b.append('Content-Disposition: form-data; name="%s"' % key) b.append('') b.append(str(value)) buf.extend(map(str.encode, b)) for(key, fd) in files: if isinstance(fd, tuple): filename, data = fd try: fd = open(filename, 'rb') except: pass else: filename, data=os.path.basename(fd.name), None contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' b = [] b.append('--' + boundary) b.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename)) b.append('Content-Type: ' + contenttype) b.append('') buf.extend(map(str.encode, b)) if data is None: try: data = fd.read() except: data = b'' buf.append(data) buf.append(('--%s--' % boundary).encode()) buf.append(sep) return boundary, sep.join(buf)
def _write_headers(self, msg): """Writes this `NetworkMessage` instance's headers to the given generator's output file with network style CR LF character pair line endings. If called during a `NetworkMessage.as_string()` to which the `write_headers` option was ``False``, this method does nothing. """ if not self.write_headers: return headerfile = self._fp unixheaderfile = StringIO() try: self._fp = unixheaderfile Generator._write_headers(self, msg) finally: self._fp = headerfile headers = unixheaderfile.getvalue() headerfile.write(headers.replace('\n', '\r\n'))
def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'): from email.message import Message msg = Message() msg['Wheel-Version'] = '1.0' # of the spec msg['Generator'] = generator msg['Root-Is-Purelib'] = str(self.root_is_pure).lower() if self.build_number is not None: msg['Build'] = self.build_number # Doesn't work for bdist_wininst impl_tag, abi_tag, plat_tag = self.get_tag() for impl in impl_tag.split('.'): for abi in abi_tag.split('.'): for plat in plat_tag.split('.'): msg['Tag'] = '-'.join((impl, abi, plat)) wheelfile_path = os.path.join(wheelfile_base, 'WHEEL') logger.info('creating %s', wheelfile_path) with open(wheelfile_path, 'w') as f: Generator(f, maxheaderlen=0).flatten(msg)
def _export_mbox(self, fp, sms): # export SMS data to mbox format _email_generator=Generator(fp, True) _lfs='\n\n' _keys=sms.keys() _keys.sort() for k in _keys: e=sms[k] try: _msg=MIMEText(e.text) _msg['From']=e._from or 'self' _msg['To']=e._to or 'self' _msg['Subject']=e.subject if e.datetime: _msg['Date']=formatdate(bptime.BPTime(e.datetime).mktime(), True) _email_generator.flatten(_msg, True) _email_generator.write(_lfs) except: if __debug__: raise
def send_email(sender, recipient, subject, text, server='localhost'): # Open the plain text file whose name is in textfile for reading. # msg = EmailMessage() # msg.set_content(text) # # # me == the sender's email address # # you == the recipient's email address # msg['Subject'] = subject # msg['Subject'] = subject # msg['From'] = sender # # # Send the message via our own SMTP server. # s = smtplib.SMTP(server) # s.send_message(msg) # s.quit() msg = MIMEMultipart('alternative') msg['Subject'] = "%s" % Header(subject, 'utf-8') # Only descriptive part of recipient and sender shall be encoded, not the email address # msg['From'] = "\"%s\" <%s>" % (Header(from_address[0], 'utf-8'), from_address[1]) # msg['To'] = "\"%s\" <%s>" % (Header(recipient[0], 'utf-8'), recipient[1]) msg['Subject'] = subject msg['From'] = sender msg['To'] = recipient # Attach both parts # htmlpart = MIMEText(html, 'html', 'UTF-8') textpart = MIMEText(text, 'plain', 'UTF-8') # msg.attach(htmlpart) msg.attach(textpart) # Create a generator and flatten message object to 'file’ str_io = StringIO() g = Generator(str_io, False) g.flatten(msg) # str_io.getvalue() contains ready to sent message # Optionally - send it – using python's smtplib # or just use Django's s = smtplib.SMTP(server) s.sendmail(sender, recipient, str_io.getvalue())
def _sendmail(fromAddress, toAddress, message, host='localhost', port=0, user=None, password=None, callback=None, errback=None): """ Connect to an SMTP server and send an email message. If username and password are provided, ESMTP is used to connect, otherwise a standard SMTP connection is used. @param fromAddress: The SMTP reverse path (ie, MAIL FROM) @param toAddress: The SMTP forward path (ie, RCPT TO) @param message: An L{email.message.Message} instance (such as C{MIMEText}). @param host: The MX host to which to connect. @param port: The port number to which to connect. @param user: The username with which to authenticate. @param password: The password with which to authenticate. @return: A Deferred which will be called back when the message has been sent or which will errback if it cannot be sent. """ if user or password: fp = StringIO() g = Generator(fp, mangle_from_=False, maxheaderlen=60) g.flatten(message) d = Deferred() factory = ESMTPSenderFactory(user, password, fromAddress, toAddress, message, d) reactor.connectTCP(host, port, factory) else: d = sendmail( host, fromAddress, toAddress, ) return d
def _maybe_decrypt_inline_encrypted_msg(self, origmsg, encoding, senderPubkey): """ Possibly decrypt an inline OpenPGP encrypted message. :param origmsg: The original, possibly encrypted message. :type origmsg: Message :param encoding: The encoding of the email message. :type encoding: str :param senderPubkey: The key of the sender of the message. :type senderPubkey: OpenPGPKey :return: A tuple containing a decrypted message and a bool indicating whether the signature is valid. :rtype: (Message, bool) """ log.msg('maybe decrypting inline encrypted msg') # serialize the original message buf = StringIO() g = Generator(buf) g.flatten(origmsg) data = buf.getvalue() # handle exactly one inline PGP message valid_sig = False if PGP_BEGIN in data: begin = data.find(PGP_BEGIN) end = data.find(PGP_END) pgp_message = data[begin:end + len(PGP_END)] try: decrdata, valid_sig = self._decrypt_and_verify_data( pgp_message, senderPubkey) # replace encrypted by decrypted content data = data.replace(pgp_message, decrdata) except keymanager_errors.DecryptError: logger.warning('Failed to decrypt potential inline encrypted ' 'message. Storing message as is...') # if message is not encrypted, return raw data if isinstance(data, unicode): data = data.encode(encoding, 'replace') return (self._parser.parsestr(data), valid_sig)
def fetch(self, ctx): """ This method applies fetch criteria that this object represents to the message and message entry being passed in. It returns the part of the message wanted as a string ready to be sent right back to the client that asked for it. NOTE: In case you are wondering a FETCH of a message can cause it to gain a '\Seen' flag. """ self.ctx = ctx # Based on the operation figure out what subroutine does the rest # of the work. # if self.attribute == "body": result = self.body(self.ctx.msg, self.section).decode() elif self.attribute == "bodystructure": result = self.bodystructure(self.ctx.msg) elif self.attribute == "envelope": result = self.envelope(self.ctx.msg) elif self.attribute == "flags": result = "(%s)" % " ".join( [constants.seq_to_flag(x) for x in self.ctx.sequences]) elif self.attribute == "internaldate": result = '"%s"' % self.ctx.internal_date.strftime( "%d-%b-%Y %H:%m:%S %z") elif self.attribute == "rfc822.size": # result = str(len(self.ctx.mailbox.mailbox.get_string( # self.ctx.msg_key))) fp = StringIO() g = Generator(fp, mangle_from_=False) g.flatten(self.ctx.msg) result = str(len(fix_eols(fp.getvalue()))) elif self.attribute == "uid": result = str(self.ctx.uid) else: raise NotImplemented return "%s %s" % (str(self), result)
def save(self, targetPath=None): """ Save email to the hard drive and return a list of parts by index, type, name. Compress the file if the filename ends with .gz Return partPacks if targetPath=None. """ message = self.as_message() # Save if targetPath: Generator((gzip.open if targetPath.endswith('.gz') else open)(targetPath, 'wb')).flatten(message) # Gather partPacks partPacks = [] for partIndex, part in enumerate(message.walk()): mainType = part.get_content_maintype() if 'multipart' == mainType: continue partName = part.get_filename() or '' partType = part.get_content_type() or '' partPack = partIndex, partName, partType partPacks.append(partPack) return partPacks
def write_wheelfile(self, wheelfile_base, generator="bdist_wheel (" + wheel_version + ")"): from email.message import Message msg = Message() msg["Wheel-Version"] = "1.0" # of the spec msg["Generator"] = generator msg["Root-Is-Purelib"] = str(self.root_is_pure).lower() # Doesn't work for bdist_wininst impl_tag, abi_tag, plat_tag = self.get_tag() for impl in impl_tag.split("."): for abi in abi_tag.split("."): for plat in plat_tag.split("."): msg["Tag"] = "-".join((impl, abi, plat)) wheelfile_path = os.path.join(wheelfile_base, "WHEEL") logger.info("creating %s", wheelfile_path) with open(wheelfile_path, "w") as f: Generator(f, maxheaderlen=0).flatten(msg)
async def _serialize_request(self, request): """ Convert an HttpRequest object into a string. Args: request: HttpRequest, the request to serialize. Returns: The request as a string in application/http format. """ parsed = urlparse(request.uri) request_line = urlunparse( ("", "", parsed.path, parsed.params, parsed.query, "")) status_line = request.method + " " + request_line + " HTTP/1.1\n" major, minor = request.headers.get("content-type", "application/json").split("/") msg = MIMENonMultipart(major, minor) headers = request.headers.copy() # MIMENonMultipart adds its own Content-Type header. if "content-type" in headers: del headers["content-type"] for key, value in headers.items(): msg[key] = value msg["Host"] = parsed.netloc msg.set_unixfrom(None) if request.body is not None: msg.set_payload(request.body) msg["content-length"] = str(len(request.body)) # Serialize the mime message. fp = StringIO() # maxheaderlen=0 means don't line wrap headers. g = Generator(fp, maxheaderlen=0) g.flatten(msg, unixfrom=False) body = fp.getvalue() return status_line + body
def sendMail(config, parts, from_addr, from_name, to_addr, subject, msgid=None, inreplyto=None): if len(parts) == 1: msg = MIMEText(parts[0]["body"], _charset="utf-8") msg.set_param("format", "flowed") else: msg = MIMEMultipart("alternative") for part in parts: alt = MIMEText(part["body"], part["subtype"], _charset="utf-8") if part["subtype"] == "plain": alt.set_param("format", "flowed") msg.attach(alt) msg["From"] = formataddr((from_name, from_addr)) msg["To"] = ",".join(to_addr) msg["Subject"] = Header(subject) if msgid: msg["Message-ID"] = msgid if inreplyto: msg["In-Reply-To"] = inreplyto # from http://wordeology.com/computer/how-to-send-good-unicode-email-with-python.html m = StringIO() g = Generator(m, False) g.flatten(msg) if "SMTP_SSL" in config: server = smtplib.SMTP_SSL(config["SMTP_HOST"]) else: server = smtplib.SMTP(config["SMTP_HOST"]) if "SMTP_USERNAME" in config: server.login(config["SMTP_USERNAME"], config["SMTP_PASSWORD"]) server.sendmail(from_addr, to_addr, m.getvalue()) sentMail = {"to": to_addr, "subject": subject} server.quit() return sentMail
def add(self, message): "See `repoze.sendmail.interfaces.IMaildir`" join = os.path.join subdir_tmp = join(self.path, 'tmp') subdir_new = join(self.path, 'new') pid = os.getpid() host = socket.gethostname() randmax = 0x7fffffff counter = 0 while True: timestamp = int(time.time()) unique = '%d.%d.%s.%d' % (timestamp, pid, host, random.randrange(randmax)) filename = join(subdir_tmp, unique) try: fd = os.open(filename, os.O_CREAT|os.O_EXCL|os.O_WRONLY, 384 # BBB Python 2 vs 3, 0o600 in octal ) except OSError: # BBB Python 2.5 compat e = sys.exc_info()[1] if e.errno != errno.EEXIST: raise # File exists counter += 1 if counter >= 1000: raise RuntimeError("Failed to create unique file name" " in %s, are we under a DoS attack?" % subdir_tmp) # NOTE: maildir.html (see above) says I should sleep for 2 time.sleep(0.1) else: break with os.fdopen(fd, 'w') as f: writer = Generator(f) writer.flatten(message) return MaildirTransactionalMessage(filename, join(subdir_new, unique))
def parse(self, data): """Parses the given string or :class:`~email.message.Message` to populate the :attr:`headers` and :attr:`message` attributes. :param data: The complete message, headers and message body. :type data: :py:obj:`str` or :class:`~email.message.Message` """ if isinstance(data, Message): outfp = cStringIO.StringIO() Generator(outfp).flatten(data, False) data = outfp.getvalue() match = header_boundary.search(data) if not match: header_data = data payload = '' else: header_data = data[:match.end(0)] payload = data[match.end(0):] headers = Parser().parsestr(header_data, True) self.headers = headers self.message = payload
def sendMail(smtp, parts, from_addr, from_name, to_addr, subject, msgid=None, inreplyto=None): s = smtplib.SMTP(smtp) if len(parts) == 1: msg = MIMEText(parts[0]['body'], _charset="utf-8") msg.set_param('format', 'flowed') else: msg = MIMEMultipart('alternative') for part in parts: alt = MIMEText(part['body'], part['subtype'], _charset="utf-8") if part['subtype'] == 'plain': alt.set_param('format', 'flowed') msg.attach(alt) readable_from = email.header.Header(charset='utf8', header_name='From') readable_from.append(from_name) readable_from.append('<%s>' % (from_addr), charset='us-ascii') msg['From'] = readable_from msg['To'] = ",".join(to_addr) msg['Subject'] = Header(subject, 'utf-8') if msgid: msg['Message-ID'] = msgid if inreplyto: msg['In-Reply-To'] = inreplyto # from http://wordeology.com/computer/how-to-send-good-unicode-email-with-python.html m = StringIO() g = Generator(m, False) g.flatten(msg) s.sendmail(from_addr, to_addr, m.getvalue()) sentMail = {"to": to_addr, "subject": subject} s.quit() return sentMail
def send_mail(self, to: Union[str, List[str]], subject: str, content: str, archive_dir: Optional[str] = None, dry_run: bool = False) -> EmailMessage: msg = EmailMessage() msg["Subject"] = subject msg["From"] = self.sender msg["To"] = to if self.reply_to: msg["Reply-to"] = self.reply_to if self.cc: msg["CC"] = self.cc msg.set_content(content) if archive_dir: archive_dir.mkdir(parents=True, exist_ok=True) filename = ( "email-" + datetime.now().strftime("%Y%m%d-%H%M%S") + "-" + re.sub(r"[^@.\w]+", "_", msg["To"]) + "-" + re.sub(r"[^@.\w]+", "_", subject) + ".eml" ) with open(archive_dir / filename, "w") as f: gen = Generator(f) gen.flatten(msg) _LOGGER.info("Saved email to %s", archive_dir / filename) _LOGGER.info("Sending email to %s: %s - %s", msg["To"], subject, content) if not dry_run: smtp = smtplib.SMTP(self.smtp_server) smtp.send_message(msg) smtp.quit() _LOGGER.info("Sent email to %s: %s - %s", msg["To"], subject, content) else: _LOGGER.warn("Would have sent email: %s", msg) return msg
def frontpage(): from services.smtp import single_message_email from email.generator import Generator import StringIO print 'send frontpage:' from email.mime.text import MIMEText starup_info = 'System Start ' + \ time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime()) msg = MIMEText(starup_info) msg['subject'] = starup_info io = StringIO.StringIO() g = Generator(io, False) # second argument means "should I mangle From?" g.flatten(msg) single_message_email.msg = io.getvalue() single_message_email.mailFrom = '[email protected]' single_message_email.mailTo = 'frontpage@localhost' single_message_email.send_messages('localhost', smtp_port)
def send_mail(sender, recipient, subject, body): # Default encoding mode set to Quoted Printable. Acts globally! Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8') msg = MIMEMultipart() msg['Subject'] = "%s" % Header(subject, 'utf-8') # Only descriptive part of recipient and sender shall be encoded, # not the email address msg['From'] = "\"%s\" <%s>" % (Header(sender[0], 'utf-8'), sender[1]) msg['To'] = "\"%s\" <%s>" % (Header(recipient[0], 'utf-8'), recipient[1]) msg.attach(MIMEText(body, 'plain', 'UTF-8')) str_io = StringIO() g = Generator(str_io, False) g.flatten(msg) try: smtpObj = smtplib.SMTP('localhost') smtpObj.sendmail('', recipient[1], str_io.getvalue()) except smtplib.SMTPException, e: print e
def generate_reply(self, message, result): try: from_mailaddr = '*****@*****.**' if message.get('Reply-To'): to = message.get('Reply-To') (to_realname, to_mailaddr) = email.utils.parseaddr(to) elif message.get('From'): to = message.get('From') (to_realname, to_mailaddr) = email.utils.parseaddr(to) msg = MIMEMultipart('encrypted', protocol='application/pgp-encrypted') msg['From'] = from_mailaddr msg['To'] = to msg['Subject'] = 'ud mailgate processing results' msg['Message-Id'] = make_msgid() msg['In-Reply-To'] = message['Message-Id'] msg['Date'] = formatdate(localtime=True) msg['Content-Disposition'] = 'inline' part1 = MIMEApplication(_data='Version: 1\n', _subtype='pgp-encrypted', _encoder=encode_7or8bit) part1['Content-Disposition'] = 'attachment' msg.attach(part1) part2 = MIMEApplication(_data=result, _subtype='octet-stream', _encoder=encode_7or8bit) part2['Content-Disposition'] = 'inline; filename="msg.asc"' msg.attach(part2) fd = StringIO.StringIO() g = Generator(fd, mangle_from_=False) g.flatten(msg) if self.options['console']: self.stdout.write(fd.getvalue() + '\n') else: s = smtplib.SMTP('localhost') s.sendmail(from_mailaddr, to_mailaddr, fd.getvalue()) s.quit() except Exception as err: raise CommandError(err)
def encode_multipart_message(message): # The message must be multipart. assert message.is_multipart() # The body length cannot yet be known. assert "Content-Length" not in message # So line-endings can be fixed-up later on, component payloads must have # no Content-Length and their Content-Transfer-Encoding must be base64 # (and not quoted-printable, which Django doesn't appear to understand). for part in message.get_payload(): assert "Content-Length" not in part assert part["Content-Transfer-Encoding"] == "base64" # Flatten the message without headers. buf = BytesIO() generator = Generator(buf, False) # Don't mangle "^From". generator._write_headers = lambda self: None # Ignore. generator.flatten(message) # Ensure the body has CRLF-delimited lines. See # http://bugs.python.org/issue1349106. body = b"\r\n".join(buf.getvalue().splitlines()) # Only now is it safe to set the content length. message.add_header("Content-Length", "%d" % len(body)) return message.items(), body
def multipart_encode(params, files, boundary=None, buf=None, sep=b'\r\n'): if buf is None: buf = [] if boundary is None: boundary = Generator._make_boundary() for (key, value) in params: b = [] b.append('--' + boundary) b.append('Content-Disposition: form-data; name="%s"' % key) b.append('') b.append(str(value)) buf.extend(map(str.encode, b)) for (key, fd) in files: if isinstance(fd, tuple): filename, data = fd try: fd = open(filename, 'rb') except: pass else: filename, data = os.path.basename(fd.name), None contenttype = mimetypes.guess_type( filename)[0] or 'application/octet-stream' b = [] b.append('--' + boundary) b.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename)) b.append('Content-Type: ' + contenttype) b.append('') buf.extend(map(str.encode, b)) if data is None: try: data = fd.read() except: data = b'' buf.append(data) buf.append(('--%s--' % boundary).encode()) buf.append(sep) return boundary, sep.join(buf)
def as_string(self, unixfrom=False, maxheaderlen=0, policy=None): """Return the entire formatted message as a string. Optional 'unixfrom', when true, means include the Unix From_ envelope header. For backward compatibility reasons, if maxheaderlen is not specified it defaults to 0, so you must override it explicitly if you want a different maxheaderlen. 'policy' is passed to the Generator instance used to serialize the mesasge; if it is not specified the policy associated with the message instance is used. If the message object contains binary data that is not encoded according to RFC standards, the non-compliant data will be replaced by unicode "unknown character" code points. """ from email.generator import Generator policy = self.policy if policy is None else policy fp = StringIO() g = Generator(fp, mangle_from_=False, maxheaderlen=maxheaderlen, policy=policy) g.flatten(self, unixfrom=unixfrom) return fp.getvalue()
def send_mail(self): '''Send email with attachments''' # create MIME message msg = MIMEMultipart() msg['From'] = self.user_email msg['To'] = self.kindle_email msg['Subject'] = 'Convert' if self.convert else 'Sent to Kindle' text = 'This email has been automatically sent by SendKindle tool.' msg.attach(MIMEText(text)) # attach files for file_path in self.files: msg.attach(self.get_attachment(file_path)) # convert MIME message to string fp = StringIO() gen = Generator(fp, mangle_from_=False) gen.flatten(msg) msg = fp.getvalue() # send email try: mail_server = smtplib.SMTP_SSL(host=self.smtp_server, port=self.smtp_port) mail_server.login(self.smtp_login, self.smtp_password) mail_server.sendmail(self.user_email, self.kindle_email, msg) mail_server.close() except smtplib.SMTPException: traceback.print_exc() message = ('Communication with your SMTP server failed. Maybe ' 'wrong connection details? Check exception details and ' 'your config file: %s' % self.conffile) print(message, file=sys.stderr) sys.exit(7) print('Sent email to %s' % self.kindle_email)
def send_standard_email(self, msg): use_ssl = int(self.settings.get('mail_use_ssl', 0)) timeout = 600 # set timeout to 5mins # redirect output to logfile on python2 on python3 debugoutput is caught with overwritten # _print_debug function if sys.version_info < (3, 0): org_smtpstderr = smtplib.stderr smtplib.stderr = logger.StderrLogger('worker.smtp') log.debug("Start sending e-mail") if use_ssl == 2: self.asyncSMTP = EmailSSL(self.settings["mail_server"], self.settings["mail_port"], timeout=timeout) else: self.asyncSMTP = Email(self.settings["mail_server"], self.settings["mail_port"], timeout=timeout) # link to logginglevel if logger.is_debug_enabled(): self.asyncSMTP.set_debuglevel(1) if use_ssl == 1: self.asyncSMTP.starttls() if self.settings["mail_password"]: self.asyncSMTP.login(str(self.settings["mail_login"]), str(self.settings["mail_password"])) # Convert message to something to send fp = StringIO() gen = Generator(fp, mangle_from_=False) gen.flatten(msg) self.asyncSMTP.sendmail(self.settings["mail_from"], self.recipent, fp.getvalue()) self.asyncSMTP.quit() self._handleSuccess() log.debug("E-mail send successfully") if sys.version_info < (3, 0): smtplib.stderr = org_smtpstderr
def send_email(data): try: gmail_user = os.environ.get('MAIL_USERNAME') gmail_password = os.environ.get('MAIL_PASSWORD') except: print('unable to import mail username/password') raise subject = 'Warning - Bandwidth speeds are low' body = 'Detected: Ping %s ms<br><br>Download %s Mbit/s<br><br> Upload %s Mbit/s' % ( data['ping'], data['download'], data['upload']) from_address = ['Bandwidth Checker', gmail_user] recipient = ['Master', gmail_user] # 'alternative' MIME type - HTML and plaintext bundled in one email msg = MIMEMultipart('alternative') msg['Subject'] = '%s' % Header(subject, 'utf-8') msg['From'] = '"%s" <%s>' % (Header(from_address[0], 'utf-8'), from_address[1]) msg['To'] = '"%s" <%s>' % (Header(recipient[0], 'utf-8'), recipient[1]) htmlpart = MIMEText(body, 'html', 'UTF-8') msg.attach(htmlpart) str_io = StringIO() g = Generator(str_io, False) g.flatten(msg) try: server = smtplib.SMTP('smtp.gmail.com', 587) server.ehlo() server.starttls() server.login(gmail_user, gmail_password) server.sendmail(gmail_user, gmail_user, str_io.getvalue()) server.close() except smtplib.SMTPException: print('Failed to send mail')
def export_messages_from_file(src_file: Path, msg_ids: Iterable[int], dest_folder: Path = None) -> None: """ Writes .eml files in a destination directory given a mailbox file (PST or mbox) and a list of message IDs """ dest_folder = (dest_folder or Path.cwd()) / src_file.stem dest_folder.mkdir(parents=True, exist_ok=True) with open_mail_archive(src_file) as archive: for msg_id in msg_ids: try: msg = extract_message_from_archive(archive, int(msg_id)) with (dest_folder / f"{msg_id}.eml").open(mode="w") as eml_file: Generator(eml_file).flatten(msg) except Exception as exc: logger.warning( f"Skipping message {msg_id} from {src_file}, reason: {exc}", exc_info=True, )
def send_email(subject, body): gmail_user = os.environ.get('MAIL_USERNAME') gmail_password = os.environ.get('MAIL_PASSWORD') if not gmail_user or not gmail_password: raise EnvironmentError('invalid user or password for sending mail') logging.debug(gmail_user) logging.debug(gmail_password) from_address = ['pynotify', gmail_user] recipient = [gmail_user, gmail_user] # 'alternative' MIME type - HTML and plaintext bundled in one email msg = MIMEMultipart('alternative') msg['Subject'] = '%s' % Header(subject, 'utf-8') msg['From'] = '"%s" <%s>' % (Header(from_address[0], 'utf-8'), from_address[1]) msg['To'] = '"%s" <%s>' % (Header(recipient[0], 'utf-8'), recipient[1]) html_body = MIMEText(body, 'html', 'UTF-8') msg.attach(html_body) str_io = StringIO() gen = Generator(str_io, False) gen.flatten(msg) try: server = smtplib.SMTP('smtp.gmail.com', 587) server.ehlo() server.starttls() server.login(gmail_user, gmail_password) server.sendmail(gmail_user, gmail_user, str_io.getvalue()) server.close() except smtplib.SMTPException as e: logging.error('Failed to send mail') logging.exception(e)
def send_email(from_address, recipient, subject, text): # Default encoding mode set to Quoted Printable. Acts globally! Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8') # 'alternative’ MIME type – HTML and plain text bundled in one e-mail message msg = MIMEMultipart('alternative') msg['Subject'] = "%s" % Header(subject, 'utf-8') # Only descriptive part of recipient and sender shall be encoded, not the email address msg['From'] = "\"%s\" <%s>" % (Header(from_address[0], 'utf-8'), from_address[1]) msg['To'] = "\"%s\" <%s>" % (Header(recipient[0], 'utf-8'), recipient[1]) # Attach both parts textpart = MIMEText(text, 'plain', 'UTF-8') msg.attach(textpart) # Create a generator and flatten message object to 'file’ str_io = StringIO() g = Generator(str_io, False) g.flatten(msg) # str_io.getvalue() contains ready to sent message # Optionally - send it – using python's smtplib # or just use Django's smtpObj = smtplib.SMTP('smtp.u-psud.fr') smtpObj.sendmail(from_address[1], recipient[1], str_io.getvalue()) #except SMTPException: # print "Error: unable to send email" # raise Exception("Mail non envoyé") #end def #end class
def python_message_to_string(msg): """Converts python message to string in a proper way""" with closing(StringIO()) as fp: g = Generator(fp, mangle_from_=False) g.flatten(msg, unixfrom=False) return fp.getvalue()
def __init__(self, outfp, mangle_from_=True, maxheaderlen=78, write_headers=True): self.write_headers = write_headers Generator.__init__(self, outfp, mangle_from_, maxheaderlen)
def __init__(self, outfp, mangle_from_=True, maxheaderlen=78, charset=None): Generator.__init__(self, outfp, mangle_from_, maxheaderlen) self.charset = charset
def send_message( self, sender: str, recipients: str, subject: str = "", body: str = "", attachments: str = None, html: bool = False, images: str = None, ) -> bool: """Send SMTP email :param sender: who is sending, ie. 'from' :param recipients: who is receiving, ie. 'to' :param subject: mail subject field :param body: mail body content :param attachments: list of filepaths to attach, defaults to [] :param html: if message content is in HTML, default `False` :param images: list of filepaths for inline use, defaults to [] Valid sender values: - First Lastname <address@domain> - address@domain Example: .. code-block:: robotframework Send Message [email protected] [email protected] ... subject=Greetings Software Robot Developer ... body=${email_body} ... attachments=${CURDIR}${/}report.pdf """ add_charset("utf-8", QP, QP, "utf-8") recipients, attachments, images = self._handle_message_parameters( recipients, attachments, images) msg = MIMEMultipart() self._add_attachments_to_msg(attachments, msg) msg["From"] = sender msg["To"] = ",".join(recipients) msg["Subject"] = Header(subject, "utf-8") if html: for im in images: im = im.strip() imname = Path(im).name body = body.replace(str(imname), f"cid:{imname}") with open(im, "rb") as f: img = MIMEImage(f.read()) img.add_header("Content-ID", f"<{imname}>") msg.attach(img) htmlpart = MIMEText(body, "html", "UTF-8") msg.attach(htmlpart) else: textpart = MIMEText(body, "plain", "UTF-8") msg.attach(textpart) for im in images: im = im.strip() imname = Path(im).name with open(im, "rb") as f: img = MIMEImage(f.read()) msg.add_header( "Content-Disposition", f"inline; filename= {imname}", ) msg.attach(img) # Create a generator and flatten message object to 'file’ str_io = StringIO() g = Generator(str_io, False) g.flatten(msg) try: self.smtp_conn.sendmail(sender, recipients, str_io.getvalue()) except Exception as err: raise ValueError(f"Send Message failed: {err}") from err return True
print "Usage: %s in_folder out_folder" % os.path.basename(sys.argv[0]) sys.exit() else: inputFolder = sys.argv[1] resultsFolder = sys.argv[2] # decode base64 encoded email bodies def b64fix(emlMsg): msg = email.message_from_file(emlMsg) msg_payload = msg.get_payload() decoded = base64.b64decode(msg_payload) msg.set_payload(decoded) return msg for filename in os.listdir(inputFolder): path = os.path.join(inputFolder, filename) outPath = os.path.join(resultsFolder, filename) if not os.path.isfile(path): continue else: with open(path, 'rU') as eml: fixed_msg = b64fix(eml) with open(outPath, 'w') as fixed_eml: g = Generator(fixed_eml) g.flatten(fixed_msg) fixed_eml.flush() fixed_eml.close() eml.close()
def __init__(self, fp, root=True): Generator.__init__(self, fp, mangle_from_=False, maxheaderlen=0) self.root = root
def method(self, **kwargs): # Don't bother with doc string, it will be over-written by createMethod. for name in kwargs.iterkeys(): if name not in parameters.argmap: raise TypeError('Got an unexpected keyword argument "%s"' % name) # Remove args that have a value of None. keys = kwargs.keys() for name in keys: if kwargs[name] is None: del kwargs[name] for name in parameters.required_params: if name not in kwargs: raise TypeError('Missing required parameter "%s"' % name) for name, regex in parameters.pattern_params.iteritems(): if name in kwargs: if isinstance(kwargs[name], basestring): pvalues = [kwargs[name]] else: pvalues = kwargs[name] for pvalue in pvalues: if re.match(regex, pvalue) is None: raise TypeError( 'Parameter "%s" value "%s" does not match the pattern "%s"' % (name, pvalue, regex)) for name, enums in parameters.enum_params.iteritems(): if name in kwargs: # We need to handle the case of a repeated enum # name differently, since we want to handle both # arg='value' and arg=['value1', 'value2'] if (name in parameters.repeated_params and not isinstance(kwargs[name], basestring)): values = kwargs[name] else: values = [kwargs[name]] for value in values: if value not in enums: raise TypeError( 'Parameter "%s" value "%s" is not an allowed value in "%s"' % (name, value, str(enums))) actual_query_params = {} actual_path_params = {} for key, value in kwargs.iteritems(): to_type = parameters.param_types.get(key, 'string') # For repeated parameters we cast each member of the list. if key in parameters.repeated_params and type(value) == type([]): cast_value = [_cast(x, to_type) for x in value] else: cast_value = _cast(value, to_type) if key in parameters.query_params: actual_query_params[parameters.argmap[key]] = cast_value if key in parameters.path_params: actual_path_params[parameters.argmap[key]] = cast_value body_value = kwargs.get('body', None) media_filename = kwargs.get('media_body', None) if self._developerKey: actual_query_params['key'] = self._developerKey model = self._model if methodName.endswith('_media'): model = MediaModel() elif 'response' not in methodDesc: model = RawModel() headers = {} headers, params, query, body = model.request(headers, actual_path_params, actual_query_params, body_value) expanded_url = uritemplate.expand(pathUrl, params) url = _urljoin(self._baseUrl, expanded_url + query) resumable = None multipart_boundary = '' if media_filename: # Ensure we end up with a valid MediaUpload object. if isinstance(media_filename, basestring): (media_mime_type, encoding) = mimetypes.guess_type(media_filename) if media_mime_type is None: raise UnknownFileType(media_filename) if not mimeparse.best_match([media_mime_type], ','.join(accept)): raise UnacceptableMimeTypeError(media_mime_type) media_upload = MediaFileUpload(media_filename, mimetype=media_mime_type) elif isinstance(media_filename, MediaUpload): media_upload = media_filename else: raise TypeError('media_filename must be str or MediaUpload.') # Check the maxSize if maxSize > 0 and media_upload.size() > maxSize: raise MediaUploadSizeError("Media larger than: %s" % maxSize) # Use the media path uri for media uploads expanded_url = uritemplate.expand(mediaPathUrl, params) url = _urljoin(self._baseUrl, expanded_url + query) if media_upload.resumable(): url = _add_query_parameter(url, 'uploadType', 'resumable') if media_upload.resumable(): # This is all we need to do for resumable, if the body exists it gets # sent in the first request, otherwise an empty body is sent. resumable = media_upload else: # A non-resumable upload if body is None: # This is a simple media upload headers['content-type'] = media_upload.mimetype() body = media_upload.getbytes(0, media_upload.size()) url = _add_query_parameter(url, 'uploadType', 'media') else: # This is a multipart/related upload. msgRoot = MIMEMultipart('related') # msgRoot should not write out it's own headers setattr(msgRoot, '_write_headers', lambda self: None) # attach the body as one part msg = MIMENonMultipart(*headers['content-type'].split('/')) msg.set_payload(body) msgRoot.attach(msg) # attach the media as the second part msg = MIMENonMultipart(*media_upload.mimetype().split('/')) msg['Content-Transfer-Encoding'] = 'binary' payload = media_upload.getbytes(0, media_upload.size()) msg.set_payload(payload) msgRoot.attach(msg) # encode the body: note that we can't use `as_string`, because # it plays games with `From ` lines. fp = StringIO.StringIO() g = Generator(fp, mangle_from_=False) g.flatten(msgRoot, unixfrom=False) body = fp.getvalue() multipart_boundary = msgRoot.get_boundary() headers['content-type'] = ( 'multipart/related; ' 'boundary="%s"') % multipart_boundary url = _add_query_parameter(url, 'uploadType', 'multipart') logger.info('URL being requested: %s %s' % (httpMethod, url)) return self._requestBuilder(self._http, model.response, url, method=httpMethod, body=body, headers=headers, methodId=methodId, resumable=resumable)
def getMessagePayload(self,part): fp = StringIO.StringIO() g = EmailGenerator(fp, mangle_from_=False) g.flatten(part, unixfrom=False) return fp.getvalue()