def handle(self, *args, **options): if len(args) != 1: print('error: Need a project.') sys.exit(1) try: project = Project.objects.get(linkname=args[0]) except Project.DoesNotExist: print("error: can't find project '%s'" % args[0]) sys.exit(1) parser = HeaderParser() query = Patch.objects.filter(project=project) count = query.count() for i, patch in enumerate(query.iterator()): if (i % 10) == 0: sys.stdout.write("%06d/%06d\r" % (i, count)) sys.stdout.flush() headers = parser.parsestr(patch.headers) new_project = find_project(headers) if new_project == patch.project: continue patch.project = new_project patch.save() series = find_series_for_patch(patch) if not series: continue series.project = new_project series.save() sys.stdout.write("%06d/%06d\r" % (count, count)) sys.stdout.write('\ndone\n')
def imap_get_fetch_header(self, email_id): ''' get header of messages return parsed header messages parameter is email_id returned from serach result ''' # check serialize cache email_cache = self.imap_unserialize_email_from_file(email_id) if email_cache: return {'status':'OK', 'msg':email_cache} email_info = self.imap_get_fetch(email_id, '(BODY[HEADER])') if email_info.get('status').lower() != 'ok': return None header = email_info.get('msg')[0][1].decode('UTF-8') #get header string then decode parser = HeaderParser() # serialize parsed_header = parser.parsestr(header) serialized_eml = {} serialized_eml['ID'] = email_id serialized_eml['From'] = parsed_header.get('From') serialized_eml['To'] = parsed_header.get('To') serialized_eml['CC'] = parsed_header.get('CC') serialized_eml['BCC'] = parsed_header.get('BCC') serialized_eml['Subject'] = parsed_header.get('Subject') serialized_eml['Date'] = parsed_header.get('Date') self.imap_serialize_email_to_file(serialized_eml) return {'status':'OK', 'msg':parsed_header}
def gmail_for_techxpo_test_refresh(): global imap_server global imap_nickname global imap_username global imap_pass global mail global unread_count_initial unread_count_current = re.search("UNSEEN (\d+)", mail.status("INBOX", "(UNSEEN)")[1][0]).group(1) if unread_count_current != unread_count_initial: mail.select() #finding total mail count where latest email = mail count status, mail_count = mail.search(None, 'ALL') mail_count = mail_count[0].split() mail_count = int(mail_count[-1]) #getting data from latest email email_data = mail.fetch(mail_count, '(BODY.PEEK[])') header_data = email_data[1][0][1] parser = HeaderParser() email_info = parser.parsestr(header_data) #email sender email_from = email_info['From'] email_from = email_from.split("<")[0] #email subject line email_subject = email_info['Subject'] #print to prompt for debugging purposes unread_count_initial = unread_count_current return "New " + imap_nickname +" from " + email_from return None
def __init__(self, server, uid): """The folder must be selected on the server before this function is called""" self.OK = False result, data = server.uid('FETCH', uid, '(UID FLAGS INTERNALDATE BODY[HEADER.FIELDS (FROM TO CC DATE SUBJECT X-GMAIL-RECEIVED MESSAGE-ID)])') # data == [("uid internaldate", "headers"), ')'] if result == 'OK': try: # The UID changes based on the selected folder, but when serializing # we always serialize the UID for AllMailFolder self['uid'] = uIdMatch.search(data[0][0]).group(1) self['flags'] = flagsMatch.search(data[0][0]).group(1) self['internaldate'] = intDateMatch.search(data[0][0]).group(1) parser = HeaderParser() msg = parser.parsestr(data[0][1], headersonly=True) self['sha1'] = EmailMsg.computeSha1(self['internaldate'], msg) # The list of folders in which this message appears self['folder'] = [] self.OK = True except: logger.exception("Error retrieving message") self.OK = False
def send(self, args): """Send an AMI request "action" given a dict of header values Keyword Arguments: args A dictionary of headers and values Returns: An email.message.Message which we could wrap with our own AMIMessage class if we were feeling industrious. You can get access the headers via: ami = SyncAMI() res = ami.send({'action': 'ping'}) res.items() => [("header", "value"), ...] res.get("header") => "value" res.get_all("header") => ["value", ...] """ headers = {} params = "?" + urlencode(args) if self.cookie is not None: headers['Cookie'] = self.cookie self.con.request("GET", self.path + params, headers=headers) res = self.con.getresponse() if res.status != 200: raise InvalidAMIResponse(res) self.cookie = res.getheader('set-cookie', None) data = res.read() parser = HeaderParser() return parser.parsestr(data)
def UploadAllEmails(self): self.LoginEmail() self.LoginDocs() retcode, msg_ids = self.mail.search(None, 'UNSEEN') assert(retcode=='OK') msg_ids = [int(msg_id) for msg_id in msg_ids[0].split()] #int-ify response for msg_id in msg_ids: retcode, data = self.mail.fetch(msg_id, '(BODY.PEEK[HEADER])') assert(retcode == 'OK') p = HeaderParser() headers = p.parsestr(data[0][1]) retcode, data = self.mail.fetch(msg_id, '(BODY.PEEK[TEXT])') assert(retcode == 'OK') message = email.message_from_string(data[0][1]) for part in message.walk(): print 'type', part.get_content_type() print 'body', part.get_payload() #self.UploadMsgAsGDoc(headers, message) self.mail.close()
def get_email_headers(filepath_list): """Decode header_text for each file""" for filepath in filepath_list: with open(filepath, 'r') as f: msg = email.message_from_file(f) # Returns a message object structure tree from an open file object parser = HeaderParser() headers = parser.parsestr(msg.as_string()) # msg.as_string returns the entire message flattened as a string & parses the headers; returns an instance object msg_id = headers['Message-ID'] date_str = headers['Date'] from_str = headers['From'] to_str = headers['To'] cc_str = headers['Cc'] bcc_str = headers['Bcc'] subject_line = headers['Subject'] #normalize data msg_id = msg_id.strip() datetime_obj = get_datetime(date_str) recipient_set = get_recipient_set(to_str, cc_str, bcc_str) sender_set = get_sender_set(from_str) subject_clean = clean_subject_line(subject_line) seed.load_database(msg_id, datetime_obj, recipient_set, sender_set, subject_clean)
def get_addresses(maildir): emails = {} for root, _dirs, files in os.walk(maildir): for fname in files: fname = os.path.join(root, fname) msg = HeaderParser().parse(open(fname)) froms = msg.get_all('from', []) tos = msg.get_all('to', []) ccs = msg.get_all('cc', []) resent_tos = msg.get_all('resent-to', []) resent_ccs = msg.get_all('resent-cc', []) all_recipients = getaddresses(froms + tos + ccs + resent_tos + resent_ccs) for (title, addr) in all_recipients: emails.setdefault(addr, set()).add(title) for addr, titles in emails.iteritems(): clean = set() for title in titles: if title.startswith('=?'): title = dheader(title) title = title.strip("'\"<>").replace('\n', ' ') if title and title != addr: clean.add(title) if clean: for title in clean: yield addr, title else: yield addr, ''
def getGooglePlay(self): typ, data = self.m.search(None, '(FROM "*****@*****.**")') messages = [] for num in data[0].split(): typ, data = self.m.fetch(num, '(RFC822)') msg = HeaderParser().parsestr(data[0][1]) payload = msg.get_payload() payload = self.parsePayload(payload) messages.append({"from":msg['From'], "to":msg['To'], "subject":msg['Subject'], "payload":payload}) soup = BeautifulSoup(payload) #print(soup.prettify()) #for link in soup.find_all('a'): # print(link.get('href')) #for link in soup.find_all('img'): # webbrowser.open(link.get('src')) for meta in soup.find_all('meta'): if meta.get('itemprop') == 'orderNumber': print meta.get('content') elif meta.get('itemprop') == 'price': print meta.get('content') elif meta.get('itemprop') == 'image': f = open(msg['Subject'],'wb') f.write(urllib.urlopen(meta.get('content')).read()) f.close() return messages
def send_message(message, payload): """ Sends the AS2 message to the partner. Takes the message and payload as arguments and posts the as2 message to the partner.""" try: # Parse the message header to a dictionary header_parser = HeaderParser() message_header = header_parser.parsestr(message.headers) # Set up the http auth if specified in the partner profile auth = None if message.partner.http_auth: auth = (message.partner.http_auth_user, message.partner.http_auth_pass) verify = True if message.partner.https_ca_cert: verify = message.partner.https_ca_cert.path # Send the AS2 message to the partner try: response = requests.post(message.partner.target_url, auth=auth, verify=verify, headers=dict(message_header.items()), data=payload) response.raise_for_status() except Exception, e: # Send mail here as2utils.senderrorreport(message, _(u'Failure during transmission of message to partner with error ' u'"%s".\n\nTo retry transmission run the management ' u'command "retryfailedas2comms".' % e)) message.status = 'R' models.Log.objects.create(message=message, status='E', text=_(u'Message send failed with error %s' % e)) return models.Log.objects.create(message=message, status='S', text=_(u'AS2 message successfully sent to partner')) # Process the MDN based on the partner profile settings if message.partner.mdn: if message.partner.mdn_mode == 'ASYNC': models.Log.objects.create(message=message, status='S', text=_(u'Requested ASYNC MDN from partner, waiting for it ........')) message.status = 'P' return # In case of Synchronous MDN the response content will be the MDN. So process it. # Get the response headers, convert key to lower case for normalization mdn_headers = dict((k.lower().replace('_', '-'), response.headers[k]) for k in response.headers) # create the mdn content with message-id and content-type header and response content mdn_content = '%s: %s\n' % ('message-id', mdn_headers['message-id']) mdn_content += '%s: %s\n\n' % ('content-type', mdn_headers['content-type']) mdn_content += response.content models.Log.objects.create(message=message, status='S', text=_(u'Synchronous mdn received from partner')) pyas2init.logger.debug('Synchronous MDN for message %s received:\n%s' % (message.message_id, mdn_content)) save_mdn(message, mdn_content) else: message.status = 'S' models.Log.objects.create(message=message, status='S', text=_(u'No MDN needed, File Transferred successfully to the partner')) # Run the post successful send command run_post_send(message)
def __init__(self, rep_file): """Init object from an open REP file object.""" # Parse the headers. self.filename = rep_file rep_parser = HeaderParser() metadata = rep_parser.parse(rep_file) header_order = iter(self.headers) try: for header_name in metadata.keys(): current_header, required = header_order.next() while header_name != current_header and not required: current_header, required = header_order.next() if header_name != current_header: raise REPError("did not deal with " "%r before having to handle %r" % (header_name, current_header), rep_file.name) except StopIteration: raise REPError("headers missing or out of order", rep_file.name) required = False try: while not required: current_header, required = header_order.next() else: raise REPError("REP is missing its %r" % (current_header,), rep_file.name) except StopIteration: pass # 'REP'. try: self.number = int(metadata['REP']) except ValueError: raise REPParseError("REP number isn't an integer", rep_file.name) # 'Title'. self.title = metadata['Title'] # 'Type'. type_ = metadata['Type'] if type_ not in self.type_values: raise REPError('%r is not a valid Type value' % (type_,), rep_file.name, self.number) self.type_ = type_ # 'Status'. status = metadata['Status'] if status not in self.status_values: raise REPError("%r is not a valid Status value" % (status,), rep_file.name, self.number) # Special case for Active REPs. if (status == u"Active" and self.type_ not in ("Process", "Informational")): raise REPError("Only Process and Informational REPs may " "have an Active status", rep_file.name, self.number) self.status = status # 'Author'. authors_and_emails = self._parse_author(metadata['Author']) if len(authors_and_emails) < 1: raise REPError("no authors found", rep_file.name, self.number) self.authors = map(Author, authors_and_emails)
def respondToEmails(username,password,response_subject,automated_response): if username == None and password == None: mains=mongo.getEntry("fields","main",{}) if mains.count() > 0: username = mains[0]["email"] password = mains[0]["password"] conn = imaplib.IMAP4_SSL("imap.gmail.com") status,user = conn.login(username,password) if status == 'OK': status,numMessages = conn.select("INBOX") if status == 'OK': status,messages = conn.search(None,"(UNSEEN)") messages = messages[0].split() if len(messages) > 0: recipients=[] parser = HeaderParser() for msg_id in messages: status,data = conn.fetch(msg_id,'(BODY[HEADER.FIELDS (FROM)])') response = parser.parsestr(data[0][1]) recipients.append(response["From"]) conn.store(msg_id,'+FLAGS','\Seen') smtpserver = smtplib.SMTP("smtp.gmail.com",587) smtpserver.ehlo() smtpserver.starttls() smtpserver.ehlo() smtpserver.login(username, password) response = email.MIMEMultipart.MIMEMultipart() response["From"]=username response["Subject"]=response_subject response.attach(email.MIMEText.MIMEText(automated_response,"plain")) smtpserver.sendmail(username,recipients,response.as_string()) smtpserver.quit() conn.close()
def main(): outdir = os.path.join(os.path.dirname('__file__'), 'build') try: shutil.rmtree(outdir) except FileNotFoundError: pass os.mkdir(outdir) filenames = [] names = {} for filename in sorted(glob.glob("pep-*.rst")): outbasename = os.path.basename(filename[:-4] + '.html') filenames.append(outbasename) outfilename = os.path.join(outdir, outbasename) pepnum = get_pepnum(outfilename) print(filename, '->', outfilename) with open(filename) as inf, open(outfilename, 'w') as outf: fix_rst_pep(inf, outf, filename, pepnum) with open(filename) as inf: parser = HeaderParser() metadata = parser.parse(inf) names[pepnum] = metadata['Title'] index_filename = os.path.join(outdir, 'index.html') print(index_filename) with open(index_filename, 'w') as f: f.write('<html><head><title>Draft PEP index</title></head>') f.write('<body><h1>Draft PEP index</h1><ul>') for filename in filenames: pepnum = get_pepnum(filename) f.write('<li>{num}: <a href="{link}">{name}</a></li>'.format( link=filename, num=pepnum, name=names[pepnum])) f.write('</ul></body></html>')
def handle_read(self): payload = self.recv(8192) self.log.debug("handle read: %d bytes" % len(payload)) self.data.write(payload) if self.maxBytes is not None and self.data.tell() > self.maxBytes: # hopefully we have enough data self.handle_close() if not self.header: # parse header self.data.seek(0) try: self.hdrEnd = self.data.getvalue().index("\r\n\r\n") + 4 except ValueError: return # continue until we have all the headers # status line is "HTTP/version status message" status = self.data.readline() self.status = status.split(" ", 2) # followed by a rfc822-style message header parser = HeaderParser() self.header = parser.parse(self.data) self.data.seek(0, os.SEEK_END) if self.log.isEnabledFor(logging.DEBUG): self.log.debug("version %s " % self.status[0]) self.log.debug("status %s %s " % tuple(self.status[1:])) for key, value in self.header.items(): self.log.debug("header %s = %s" % (key, value)) if self.status[1] != "200": self.log.error("status = %s %s" % tuple(self.status[1:])) self.close()
def get_mail_details(): r=raw_input("\nEnter the mail number:\n") data = mail.fetch(r, '(BODY[HEADER])') header_data = data[1][0][1] parser = HeaderParser() msg = parser.parsestr(header_data) print "\nFrom: "+msg['From'],"\nTo: "+msg['To'],"\nSubject: "+msg['Subject'],"\nDate: "+msg['Date']+"\n"
def checkMailForNewCommands(): logger.info('checking gmail for commands...') conn = imaplib.IMAP4_SSL(imap_server) try: (retcode, capabilities) = conn.login(USERNAME, PASSWORD) except: logger.error(sys.exc_info()[1]) sys.exit(1) conn.select() # Select inbox or default namespace (retcode, messages) = conn.uid('search', None, '(UNSEEN)') if retcode == 'OK': for uid in messages[0].split(): logger.info('Found an unread message with id: ' + uid) data = conn.uid('fetch', uid, '(BODY[HEADER])') header_data = data[1][0][1] parser = HeaderParser() msg = parser.parsestr(header_data) subjectText = msg["Subject"].lower() if not subjectText.startswith("[command]"): continue # if we've already processed this email, move on if uid in completedCommands: continue commandString = subjectText.split("[command]")[1].strip() completedCommands[uid] = commandString markCommandMailAsRead(conn, uid) sendCommand(commandString) pickle.dump(completedCommands, open(storageFileName, "wb")) conn.close()
def main(): mail = imaplib.IMAP4_SSL('imap.gmail.com')#tested with gmail but should work with any IMAP email mail.login('*****@*****.**', 'password')#set this mail.list() mail.select("inbox") #Grab all the messages and pull header information from them #(Restricted by date just because my inbox has thousands of messages ^_^;;; #Otherwise should be mail.uid('search',None,"ALL") ) result, data = mail.uid('search',"(SINCE 22-Nov-2012)") #search and return unique ids http://tools.ietf.org/html/rfc3501#section-6.4.4 messages = data[0].split() emails = [] for uid in messages: result, data = mail.uid('fetch', uid, '(RFC822.SIZE BODY[HEADER.FIELDS (SUBJECT TO FROM RECEIVED)])') #Fetch just desired data raw_email = data[0][1] parser = HeaderParser() msg = parser.parsestr(raw_email) #Reorganizing the data for the template #probably a much better way to do this, interested in knowing it ^_^;;; email = dict() email['From'] = msg['From'] email['To'] = msg['To'] email['Subject'] = msg['Subject'] email['Received'] = msg['Received'] #Returns IP addresses and SMTP id as well. emails.append(email) return render_template('messages.html', msg=emails)
def find_emails_by_subject(self, subject, limit=50): """ Searches for Email by Subject. Returns email's imap message IDs as a list if matching subjects is found. Args: subject (str) - Subject to search for. Kwargs: limit (int) - Limit search to X number of matches, default 50 Returns: list - List of Integers representing imap message UIDs. """ # Select inbox to fetch the latest mail on server. self._mail.select("inbox") matches = [] parser = HeaderParser() matching_msg_nums = self.__search_email_by_subject(subject) for msg_num in matching_msg_nums[-limit:]: _, msg_data = self._mail.fetch(msg_num, '(RFC822)') raw_msg = msg_data[0][1] msg_headers = parser.parsestr(raw_msg, True) if msg_headers['subject'] == subject: uid = re.search("UID\\D*(\\d+)\\D*", self._mail.fetch(msg_num, 'UID')[1][0]).group(1) matches.append(uid) return matches
def fetch_header(self, email_id, location='INBOX'): status, header = self.imap_conn.select(location) header = None t, header = self.imap_conn.fetch(email_id, '(BODY[HEADER])') header_data = header[0][1].decode('utf-8', 'ignore') parser = HeaderParser() header = parser.parsestr(header_data) return header
def fetch_and_store(): detach_dir = '.' m = imaplib.IMAP4_SSL("imap.gmail.com") m.login('*****@*****.**',getPassword()) m.select("inbox") resp, items = m.search(None, "(UNSEEN)") items = items[0].split() for emailid in items: resp, data = m.fetch(emailid, "(RFC822)") email_body = data[0][1] resp2, header = m.fetch(emailid, '(BODY[HEADER.FIELDS (SUBJECT)])') subject = header[0][1] parser = HeaderParser() msg = parser.parsestr(subject) subjectline = "".join(re.findall(r'[0-9a-zA-Z\-]', msg["Subject"])) mail = email.message_from_string(email_body) from email.utils import parseaddr fromaddr = parseaddr(mail['from'])[1] name = parseaddr(mail['from'])[0] temp = m.store(emailid,'+FLAGS', '\\Seen') m.expunge() sender = checkSender(fromaddr) if not parseSubLine(subjectline) or not sender : #Ifall mailet har fel rubrik, går vi in här if not parseSubLine(subjectline) : print "Warning: Mail has wrong subject" sendEmail(name, fromaddr, subjectline, "2") #Skickar ett mail till avsändaren om att dess mail haft fel format på rubriken elif not sender : print "Warning: Address not in senders file" sendEmail(name, fromaddr, subjectline, "1") #Skickar ett mail till avsändaren om adressen inte finns i "sender.txt"-listan else: if not os.path.exists(subjectline): os.makedirs(subjectline) if mail.get_content_maintype() != 'multipart': continue filenamelist = [] for part in mail.walk(): if part.get_content_maintype() == 'multipart': continue if part.get('Content-Disposition') is None: continue filename = "".join(re.findall(r'[.0-9a-zA-Z\-]',part.get_filename())) att_path = os.path.join(detach_dir + "/" + subjectline, filename) filenamelist.append(filename) if not os.path.isfile(att_path) : fp = open(att_path, 'wb') fp.write(part.get_payload(decode=True)) fp.close() course = sender[0] name = sender[1] dest = "www/uppladdat/" + course + "/{0}.pdf".format(setFileName(sender,subjectline)) convertStoredToPdf(subjectline, dest)
def fetch_and_parse(self, ids, query): data = self.fetch(ids, query) parser = HeaderParser() emails = [] for email in data: if len(email) < 2: continue emails.append(parser.parsestr(email[1]) ) return emails
class EmailMessage(object): def __init__(self, raw_data): self.raw_data = raw_data self.parsed_data = HeaderParser().parsestr(self.raw_data[0][1]) def _decode(self, parsed_data): return " ".join(map(_decode_token, email.header.decode_header(parsed_data))) def get_from(self): return self._decode(self.parsed_data['From']) def get_from_email(self): matches = re.search(r'[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}', self.get_from()) if matches is not None: return matches.group(0) return None def get_to(self): return self._decode(self.parsed_data['To']) def get_subject(self): return self._decode(self.parsed_data['Subject']) def get_reply_to(self): return self._decode(self.parsed_data['Reply-To']) def get_received_on(self): return datetime.fromtimestamp(time.mktime(email.utils.parsedate(self.parsed_data['Received'].split("\n")[1].strip()))) def get_content(self, content_type='plain'): mail = email.message_from_string(self.raw_data[0][1]) payloads = [] for part in mail.walk(): # multipart are just containers, so we skip them if part.get_content_maintype() == 'multipart': continue # we are interested only in the given content_type if part.get_content_subtype() != content_type: continue payloads.append(part.get_payload(decode=True)) content = " ".join(payloads) if self.parsed_data.get_content_charset() is not None: content = unicode(content, self.parsed_data.get_content_charset()) else: enc = chardet.detect(content)['encoding'] if not enc in ENC_GUESS_LIST: enc = ENC_DEFAULT content = unicode(content, enc) return content
def delete_draft(self, inbox_uid): """ Move the message from the "Drafts" folder and into the "Trash" folder. Parameters ---------- inbox_uid : str The public_id of the draft we want to delete on the remote, which is its X-INBOX-ID header too. Notes ----- Need the public_id == inbox_uid since that is the only unique identifier for the message that both we and the remote know. """ assert inbox_uid criteria = ['DRAFT', 'NOT DELETED'] all_draft_uids = self.conn.search(criteria) # It would be nice to just search by X-INBOX-ID header too, but some # backends don't support that. So fetch the header for each draft and # see if we can find one that matches. # TODO(emfree): are there other ways we can narrow the result set a # priori (by subject or date, etc.) matching_draft_headers = self.conn.fetch( all_draft_uids, ['BODY.PEEK[HEADER]']) for uid, response in matching_draft_headers.iteritems(): headers = response['BODY[HEADER]'] parser = HeaderParser() x_inbox_id = parser.parsestr(headers).get('X-Inbox-Id') if x_inbox_id == inbox_uid: # TODO: do we need this part? # Remove IMAP `Draft` label self.conn.remove_flags([uid], ['\Draft']) self.conn.delete_messages([uid]) self.conn.expunge() # Delete from `Trash` # Needed because otherwise deleting a draft that was sent # results in it synced twice - once via the Trash folder and # once via the Sent folder. self.conn.select_folder(self.folder_names()['trash']) all_trash_uids = self.conn.search() all_trash_headers = self.conn.fetch(all_trash_uids, ['BODY.PEEK[HEADER]']) for u, r in all_trash_headers.iteritems(): x_inbox_header = HeaderParser().parsestr( r['BODY[HEADER]']).get('X-Inbox-Id') if x_inbox_header == inbox_uid: self.conn.delete_messages([u]) self.conn.expunge() return
def list_pypi_addons(): """ List add-ons available on pypi. """ from ..config import ADDON_PYPI_SEARCH_SPEC import xmlrpc.client pypi = xmlrpc.client.ServerProxy("http://pypi.python.org/pypi") addons = pypi.search(ADDON_PYPI_SEARCH_SPEC) for addon in OFFICIAL_ADDONS: if not any(a for a in addons if a['name'] == addon): versions = pypi.package_releases(addon) if versions: addons.append({"name": addon, "version": max(versions)}) multicall = xmlrpc.client.MultiCall(pypi) for addon in addons: name, version = addon["name"], addon["version"] multicall.release_data(name, version) multicall.release_urls(name, version) results = list(multicall()) release_data = results[::2] release_urls = results[1::2] packages = [] for release, urls in zip(release_data, release_urls): if release and urls: # ignore releases without actual source/wheel/egg files, # or with empty metadata (deleted from PyPi?). urls = [ReleaseUrl(url["filename"], url["url"], url["size"], url["python_version"], url["packagetype"]) for url in urls] packages.append( Installable(release["name"], release["version"], release["summary"], release["description"], release["package_url"], urls) ) # Also add installed packages that have the correct keyword but # perhaps aren't featured on PyPI for dist in pkg_resources.working_set: info = HeaderParser().parsestr( '\n'.join(dist.get_metadata_lines(dist.PKG_INFO))) if ADDON_KEYWORD in info.get('Keywords', ''): packages.append( Installable(dist.project_name, dist.version, info.get('Summary', ''), info.get('Description', ''), '', []) ) return packages
def parse_request(self, request): status = request.splitlines()[0] no_status_response = '\n'.join(request.splitlines()[1:]) header_parser = HeaderParser() mime_message = header_parser.parsestr(no_status_response) mime_headers = dict(mime_message.items()) mime_body = mime_message.get_payload() return status, mime_headers, mime_body
def get_subject(self, msg_id=None): data = self.mail_connection.uid('FETCH', msg_id, '(BODY[HEADER.FIELDS (SUBJECT FROM)])') header_data = data[1][0][1] parser = HeaderParser() header = parser.parsestr(header_data) subject = header['Subject'] text, encoding = email.Header.decode_header(subject)[0] if encoding is None: return text else: return text.decode(encoding)
def version_from_pkginfo(): from email.parser import HeaderParser parser = HeaderParser() try: with open('PKG-INFO') as file: pkg_info = parser.parse(file) except FileNotFoundError: print('This is not a regular source distribution!') return None print('Retrieving the distribution version from PKG-SOURCES.') return pkg_info['Version']
def gather_info(self): """Walk through emails within selected label and collect info.""" self.M.select(self.label) rc, data = self.M.search(None, 'ALL') i = 1 if testcase: # for debugging only: can choose a single email to test on. (set at top) print '\n-------- SINGLE TESTCASE:', testcase resp, header = self.M.FETCH(testcase, '(BODY[HEADER])') msg = HeaderParser().parsestr(header[0][1]) e_sub = re_sub(msg['Subject']) print msg['From'], '---' e_from = extract_emails(msg['From']) e_to = extract_emails(msg['To']) e_cc = extract_emails(msg['CC']) for key in msg.keys(): print key, ':\n', msg[key], '\n' print 'Sub:', e_sub print 'Frm:', e_from print 'To: ', e_to print 'CC: ' for email in e_cc: print '\t', email #print 'Dte:', e_date print '\n' else: # normal functionality - iterates over labels returned num list. total = self.get_count() for num in data[0].split(): #percent_done = get_percentage(i, total) print 'Grabbing', str(num).zfill(len(total)), 'of', total#, '\tComplete:', percent_done resp, header = self.M.FETCH(num, '(BODY[HEADER])') if debug: print 'header_data:\n', header msg = HeaderParser().parsestr(header[0][1]) e_sub = re_sub(msg['Subject']) e_from = extract_emails(msg['From']) e_to = extract_emails(msg['To']) e_cc = extract_emails(msg['CC']) #e_date = date_to_epoch(msg['Date']) self.add_info_norm(e_sub, e_from, e_to, e_cc) if debug: print 'Sub: ', e_sub print 'Frm: ', e_from print 'To: ', e_to print 'CC: ' for email in e_cc: print '\t', email #print 'Date:', e_date print '\n' i += 1 if limit: if i > max_limit: print '\nReached "max_limit" of', max_limit, '- Ending c.gather_info()\n' break
def getAmazon(self): typ, data = self.m.search(None, '(FROM "*****@*****.**")') messages = [] for num in data[0].split(): typ, data = self.m.fetch(num, '(RFC822)') #print 'Message %s\n%s\n' % (num, data[0][1]) msg = HeaderParser().parsestr(data[0][1]) payload = msg.get_payload() payload = self.parsePayload(payload) messages.append({"from":msg['From'], "to":msg['To'], "subject":msg['Subject'], "payload":payload}) return messages
def build_references_from_mail(mail): replies = "" references = "" parser = HeaderParser() headers = parser.parsestr(mail.as_string()) for h in headers.items(): # Patch emails created with send-pull-Request script # may contain two set of references, so use only the oldest if h[0] == 'In-Reply-To': replies = "%s" % h[1] if h[0] == 'References': references = "%s" % h[1] return build_references_from_headers(replies, references)
def get_headers(self, Email): headers = None try: parser = HeaderParser() raw_headers = parser.parsestr(Email.as_string()) #headers = dict() headers = "" for key, value in raw_headers.items(): # headers[str(key).lower()] = str(value).lower() headers += str(key).lower() + ": " + str(value).lower() + "|" except Exception as e: print "Emailtoolkit: headers error", e finally: return headers
def _read_metadata(cls, fpath): """ Read the original format which is stored as RFC-822 headers. """ data = odict() if fpath and isfile(fpath): parser = HeaderParser() # FIXME: Is this a correct assumption for the encoding? # This was needed due to some errors on windows with open(fpath) as fp: data = parser.parse(fp) return cls._message_to_dict(data)
def __init__(self, pep_file): super(PEP, self).__init__(pep_file) pep_file.seek(0) parser = HeaderParser() self.metadata = metadata = parser.parse(pep_file) date_string = metadata['Created'] if date_string: self.created = parse_date( RE_BAD_SUFFIX.sub('', metadata['Created'])) else: self.created = None
def _fetch_emails_by_ids(self, email_ids, mailbox=None): if mailbox and mailbox != self.selected_mailbox: self._select_mailbox(mailbox) if not self.selected_mailbox: raise ValueError('No Mailbox selected') if isinstance(email_ids, (list, tuple)): email_ids = ','.join(email_ids) self.log('fetch %s' % email_ids) ret, data = self.connection.fetch(email_ids, DEFAULT_FETCH_PARTS) self.log(ret) data = (d for d in data if isinstance(d, tuple)) parser = HeaderParser() data = ((self.__parse_fetch_response(status), parser.parsestr(header)) for status, header in data) return data
def check_email_get_targets(): status, email_ids = imap_server.search(None, '(UNSEEN)') if email_ids == ['']: print('No Unread Emails') targets_list = [] else: for e_id in email_ids[0].split(): resp, data = imap_server.fetch(e_id, '(RFC822)') perf = HeaderParser().parsestr(data[0][1]) print('Perf: ' , perf) targets_list.append(perf['To']) print('List of Targets: ', targets_list) imap_server.close() return targets_list if __name__ == '__main__': imap_server = imaplib.IMAP4_SSL("imap.gmail.com",993) imap_server.login(USERNAME, PASSWORD) imap_server.select('INBOX') target_list = check_email_get_targets() if target_list : print("I got an email") else: print("I got no email")
def get_senders(email_ids): senders_list = [] #create list for e_id in email_ids[0].split(): #Loops new emails resp, data = imap_server.fetch(e_id, '(RFC822)') #fetch it perf = HeaderParser().parsestr(data[0][1]) #parse it senders_list.append(perf['From']) #get from return senders_list
def get_senders(email_ids): senders_list = [] #creates senders_list list for e_id in email_ids[0].split(): #Loops IDs of a new emails created from email_ids = imap_server.search(None, '(UNSEEN)') resp, data = imap_server.fetch(e_id, '(RFC822)') #FETCH command retrieves data associated with a message in the mailbox. The data items to be fetched can be either a single atom or a parenthesized list. Returned data are tuples of message part envelope and data. perf = HeaderParser().parsestr(data[0][1]) #parsing the headers of message senders_list.append(perf['From']) #Looks through the data parsed in "perf", extracts the "From" field return senders_list
def __init__(self, incommingmail): #read an parse mail header parser = HeaderParser() self.orig_msg = parser.parsestr(incommingmail) # read subject self.orig_subject = self.orig_msg.get('Subject') # read received, ignore all but last self.orig_received = self.orig_msg.get_all('Received')[0] # read sender self.returnsender = self.orig_msg['Return-Path'] or self.orig_msg[ 'From'] #replay adress self.sender_domain = self.get_domain(self.returnsender) self.orig_receiver = self.orig_msg.get("To") self.reply_address = "noreply@{}".format( self.get_domain(self.orig_receiver))
def send(self, args): """Send an AMI request "action" given a dict of header values Keyword Arguments: args A dictionary of headers and values Returns: An email.message.Message which we could wrap with our own AMIMessage class if we were feeling industrious. You can get access the headers via: ami = SyncAMI() res = ami.send({'action': 'ping'}) res.items() => [("header", "value"), ...] res.get("header") => "value" res.get_all("header") => ["value", ...] """ headers = {} params = "?" + urlencode(args) if self.cookie is not None: headers['Cookie'] = self.cookie self.con.request("GET", self.path + params, headers=headers) res = self.con.getresponse() if res.status != 200: raise InvalidAMIResponse(res) self.cookie = res.getheader('set-cookie', None) data = StringIO(res.read().decode('utf-8', 'ignore')) res = HeaderParser().parse(data) data.close() return res
def get_message_headers(self, message_content): headers_fields = ['From', 'To', 'Subject', 'Date'] headers = {} parser = HeaderParser().parsestr(message_content) for field in headers_fields: headers[field] = parser[field] return headers
def get_verification_code(credentialsFile, email_info): LOGGER.debug('Getting verification code...') parser = HeaderParser() con = connect(*get_credentials(credentialsFile)) msgs = get_emails(con, search_for(con, email_info)) for msg in msgs[::-1]: for sent in msg: if type(sent) is tuple: content = str(sent[1], 'utf-8') data = str(content) headers = parser.parsestr(data) subject = headers['Subject'] code = subject.split(' ')[-1] LOGGER.debug('Verification Code: {}'.format(code)) return code
def setup(): global TTS global PARSER global IMAP_SERVER global MAIL_SERVERS IMAP_SERVER = None PARSER = HeaderParser() TTS = pyttsx3.init() TTS.say(' ') TTS.runAndWait() MAIL_SERVERS = { 'gmail.com': { 'Server': str(socket.gethostbyname('imap.gmail.com')) }, 'yahoo.com': { 'Server': str(socket.gethostbyname('imap.mail.yahoo.com')) }, 'aol.com': { 'Server': str(socket.gethostbyname('imap.aol.com')) } }
def setUpTestData(cls): # Every test needs a client. cls.client = Client() cls.header_parser = HeaderParser() # Load the client and server certificates cls.server_key = models.PrivateCertificate.objects.create( certificate=os.path.join(TEST_DIR, 'as2server.pem'), certificate_passphrase='password') cls.si_public_key = models.PublicCertificate.objects.create( certificate=os.path.join(TEST_DIR, 'si_public_key.crt'), ca_cert=os.path.join(TEST_DIR, 'si_public_key.ca'), verify_cert=False) # Setup the server organization and partner cls.organization = models.Organization.objects.create( name='Server Organization', as2_name='as2server', encryption_key=cls.server_key, signature_key=cls.server_key) cls.partner = models.Partner.objects.create( name='Sterling B2B Integrator', as2_name='SIAS2PRD', target_url='http://localhost:8080/pyas2/as2receive', compress=False, mdn=False, signature_key=cls.si_public_key, encryption_key=cls.si_public_key) # Initialise the payload i.e. the file to be transmitted cls.payload = models.Payload.objects.create( name='testmessage.edi', file=os.path.join(TEST_DIR, 'testmessage.edi'), content_type='application/edi-consent')
def get_subjects(email_ids): subjects_list = [] for e_id in email_ids[0].split(): resp, data = imap_server.fetch(e_id, '(RFC822)') perf = HeaderParser().parsestr(data[0][1]) subjects_list.append(perf['Subject']) return subjects_list
def get(self, request, pk, *args, **kwargs): try: message = models.Message.objects.get(message_id=pk) payload = message.payload if request.GET['action'] == 'downl': response = HttpResponse(content_type=payload.content_type) dispositiontype = 'attachment' response['Content-Disposition'] = dispositiontype + '; filename=' + payload.name response.write(as2utils.readdata(payload.file)) return response elif request.GET['action'] == 'this': file_obj = dict() file_obj['name'] = payload.name file_obj['id'] = pk file_obj['content'] = as2utils.readdata(payload.file,charset='utf-8',errors='ignore') if payload.content_type == 'application/EDI-X12': file_obj['content'] = viewlib.indent_x12(file_obj['content']) elif payload.content_type == 'application/EDIFACT': file_obj['content'] = viewlib.indent_edifact(file_obj['content']) elif payload.content_type == 'application/XML': file_obj['content'] = viewlib.indent_xml(file_obj['content']) file_obj['direction'] = message.get_direction_display() file_obj['type'] = 'AS2 MESSAGE' file_obj['headers'] = dict(HeaderParser().parsestr(message.headers or '').items()) return render(request,self.template_name,{'file_obj': file_obj}) except Exception,e: return render(request,self.template_name,{'error_content': _(u'No such file.')})
def __init__(self, folder, num, msg): self.num = num self.folder = folder self.msg = email.message_from_string(msg) parser = HeaderParser() hdr = parser.parsestr(msg) self.subject = MailboxMessage.decode_header(hdr['Subject']) self.sender = MailboxMessage.decode_header(hdr['From']) # Now convert to local date-time self.raw_date = hdr['Date'] date_tuple = email.utils.parsedate_tz(self.raw_date) if date_tuple: self.local_date = datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_tuple))
def get(self, request, pk, *args, **kwargs): try: mdn = models.MDN.objects.get(message_id=pk) if request.GET['action'] == 'downl': response = HttpResponse(content_type='multipart/report') disposition_type = 'attachment' response[ 'Content-Disposition'] = disposition_type + '; filename=' + pk + '.mdn' response.write(as2utils.readdata(mdn.file)) return response elif request.GET['action'] == 'this': file_obj = dict() file_obj['name'] = pk + '.mdn' file_obj['id'] = pk file_obj['content'] = as2utils.readdata(mdn.file, charset='utf-8', errors='ignore') file_obj['direction'] = mdn.get_status_display() file_obj['type'] = 'AS2 MDN' file_obj['headers'] = dict(HeaderParser().parsestr( mdn.headers or '').items()) return render(request, self.template_name, {'file_obj': file_obj}) except Exception: return render(request, self.template_name, {'error_content': _(u'No such file.')})
def _delete_sent_mail(): """ delete sent mails @gmail.com Gmail keeps a copy in 'Sent Mail' folder for each mail sent. delete mails in the folder :return: """ for mb in [ 'INBOX', '[Gmail]/All Mail', '[Gmail]/Sent Mail', '[Gmail]/Spam', '[Gmail]/Trash' ]: M = imaplib.IMAP4_SSL(sender['IMAP'], 993) username = sender['Email'] M.login(username, sender['Password']) rv, data = M.select(mailbox=M._quote(mb)) if rv == 'OK': rv, data = M.uid('search', None, "ALL") if rv != 'OK': print("there is no message in '{mb}'".format(mb=mb)) return uids = data[0] uid2delete = [] for uid in uids.split(): rv, _data = M.uid('fetch', uid, '(BODY.PEEK[HEADER])') if rv != 'OK': print("ERROR getting message {uid}: {rv}".format( uid=str(uid), rv=rv)) continue # avoid decode error try: header_data = _data[0][1].decode('utf-8') parser = HeaderParser() msg = parser.parsestr(header_data) hdr = email.header.decode_header(msg['Subject']) _subject = hdr[0][0].decode(hdr[0][1]) print("delete {mb}: {_subject}".format( mb=mb, _subject=_subject).encode()) except Exception as e: pass uid2delete.append(uid.decode()) for _uid in uid2delete: M.uid('store', _uid, '+FLAGS', '(\\Deleted)') M.expunge() M.close() else: print('ERROR: unable to open "{mb}". '.format(mb=mb) + rv) M.logout()
def parse_checksum(header: str) -> str: """ Parse the Checksum header (eg. from the email epilogue) """ # Epilogue example: # "Checksum: e231f8e724890aca477ca5efdfc7bc9c31e1da124510b4f420ebcf9c2d1fbe74\r\n" msg = HeaderParser().parsestr(header) return msg["Checksum"] # type: ignore
def listMails(self): list = [] code, cnt = self.M.select() for i in range(1, int(cnt[0]) + 1): uid = map( int, re.findall(r'\d+ \(UID (\d+)\)', self.M.fetch(i, '(UID)')[1][0]))[0] header_str = self.M.fetch(i, 'RFC822.HEADER')[1][0][1] header = HeaderParser().parsestr(header_str, True) subject = header.get('SUBJECT') m_mail = Email() m_mail.header = header_str m_mail.uid = uid list.append(m_mail) return (list)
def subjects_inbox(): """ get all subject prefix in 'Inbox' of mail @163.com :return: """ # mail subjects subjects = [] M = imaplib.IMAP4_SSL(receiver['IMAP'], 993) # M.debug = 7 M.login(receiver['Email'], receiver['Password']) # mail folders t = M.list() # print(t) mb = 'INBOX' rv, data = M.select(mailbox=M._quote(mb)) if rv == 'OK': rv, data = M.uid('search', None, "ALL") if rv != 'OK': print("there is no message in {mb}".format(mb=mb)) return uids = data[0] for uid in uids.split(): rv, _data = M.uid('fetch', uid, '(BODY.PEEK[HEADER])') if rv != 'OK': # Fetch volume limit exceed. # Please try next day print("ERROR getting message {uid}: {rv} {_data}".format( uid=str(uid), rv=rv, _data=_data)) continue header_data = _data[0][1].decode('utf-8') parser = HeaderParser() msg = parser.parsestr(header_data) hdr = email.header.decode_header(msg['Subject']) _subject = hdr[0][0] if type( hdr[0][0]) == type('str') else hdr[0][0].decode(hdr[0][1]) print(('{mb}: ' + _subject).format(mb=mb).encode()) subjects.append(_subject) M.close() else: print("ERROR: unable to open {mb}. ".format(mb=mb) + rv) M.logout() return subjects
def send_async_mdn(self): """ Send the asynchronous MDN to the partner""" # convert the mdn headers to dictionary headers = HeaderParser().parsestr(self.headers.read().decode()) # Send the mdn to the partner try: response = requests.post(self.return_url, headers=dict(headers.items()), data=self.payload.read()) response.raise_for_status() except requests.exceptions.RequestException: return # Update the status of the MDN self.status = "S"
def get_messages(): mail = imaplib.IMAP4_SSL( app.config['MAIL_SERVER'] ) #tested with gmail but should work with any IMAP email mail.login(app.config['EMAIL_ADDRESS'], app.config['EMAIL_PASSWORD']) #set this in config.py mail.select("inbox") #Grab all the messages and pull header information from them #(Restricted by date just because my inbox has thousands of messages ^_^;;; #Otherwise should be mail.uid('search',None,"ALL") ) result, data = mail.uid( 'search', "(SINCE 9-Dec-2012)" ) #search and return unique ids http://tools.ietf.org/html/rfc3501#section-6.4.4 messages = data[0].split() emails = [] for uid in messages: result, data = mail.uid( 'fetch', uid, '(RFC822.SIZE BODY[HEADER.FIELDS (SUBJECT TO FROM RECEIVED)])' ) #Fetch just desired data raw_email = data[0][1] parser = HeaderParser() msg = parser.parsestr(raw_email) #Reorganizing the data for the template #probably a much better way to do this, interested in knowing it ^_^;;; from_email_id = fetch_user_id(msg['From']) to_email_id = fetch_user_id(msg['To']) try: email = { 'From': from_email_id[0], 'To': to_email_id[0], 'Subject': msg['Subject'], 'Received': msg['Received'].split(";")[ 1] #Separate the date from IP address, etc } if db_interface.check_email_exists(email) is False: db_interface.add_email_message(email) emails.append(email) except: break return emails
def get_from(patch, charset): if patch.headers: headers = HeaderParser().parsestr(patch.headers) if 'From' in headers: return headers['From'] # just in case we don't have headers in some old patches return email.utils.formataddr( (str(Header(patch.submitter.name, charset)), patch.submitter.email))
def __init__(self, host, username, pass_var, label='', x_gmail_fetch_info=''): """Initialize a new IMAP mailbox. `host`, `username` - those for the corresponding IMAP mailbox ``pass_var` - name of the environment variable containing the password for this mailbox `label` - optional label to assign when messages from this mailbox are transferred to another mailbox `x_gmail_fetch_info` - optional `X-Gmail-Fetch-Info` to add to messages before they are transferred to another mailbox """ self._host = host self._username = username self._pass_var = pass_var self._label = label self._x_gmail_fetch_info = x_gmail_fetch_info self._parser = HeaderParser() self._login()
def find_by_header(self, header_name, header_value): """Find all uids in the selected folder with the given header value.""" all_uids = self.all_uids() # It would be nice to just search by header too, but some backends # don't support that, at least not if you want to search by X-INBOX-ID # header. So fetch the header for each draft and see if we # can find one that matches. # TODO(emfree): are there other ways we can narrow the result set a # priori (by subject or date, etc.) matching_draft_headers = self.fetch_headers(all_uids) results = [] for uid, response in matching_draft_headers.iteritems(): headers = response['BODY[HEADER]'] parser = HeaderParser() header = parser.parsestr(headers).get(header_name) if header == header_value: results.append(uid) return results
def test_install(self): """Install the current project in the virtual environment.""" # This call should not throw an exception checked_subprocess_run(f"{self.python} -m pip install .") # Check the version number from `pip info` info, _ = checked_subprocess_run( f"{self.python} -m pip show {PACKAGE_NAME}") # The info section from pip is formatted as a RFC 2882 mail header. parser = HeaderParser() data = parser.parsestr(info) version = data["version"] # Version should be set, should not be the default 0.0.0, and should # match __version__ set in the package. self.assertTrue(version) self.assertNotEqual(version, "0.0.0") self.assertEqual(version, __version__)
def getHeaders(): root = Tk() root.filename = tkFileDialog.askopenfilename(initialdir="/", title="Select file") buf = open(root.filename, "rb") msg = email.message_from_file(buf) try: parser = HeaderParser() h = parser.parsestr(str(msg)) for i in h.items(): for p in i: print(p + "\n") except Exception as e: print(e) root.destroy() emailMenu()
def handle(self, *args, **options): # First part of script sends asynchronous MDNs for inbound messages received from partners # Fetch all the pending asynchronous MDN objects pyas2init.logger.info(_(u'Sending all pending asynchronous MDNs')) in_pending_mdns = models.MDN.objects.filter( status='P') # , timestamp__gt=time_threshold) --> why do this? for pending_mdn in in_pending_mdns: # Parse the MDN headers from text header_parser = HeaderParser() mdn_headers = header_parser.parsestr(pending_mdn.headers) try: # Set http basic auth if enabled in the partner profile auth = None if pending_mdn.omessage.partner and pending_mdn.omessage.partner.http_auth: auth = (pending_mdn.omessage.partner.http_auth_user, pending_mdn.omessage.partner.http_auth_pass) # Set the ca cert if given in the partner profile verify = True if pending_mdn.omessage.partner.https_ca_cert: verify = pending_mdn.omessage.partner.https_ca_cert.path # Post the MDN message to the url provided on the original as2 message with open(pending_mdn.file, 'rb') as payload: requests.post(pending_mdn.return_url, auth=auth, verify=verify, headers=dict(mdn_headers.items()), data=payload) pending_mdn.status = 'S' models.Log.objects.create( message=pending_mdn.omessage, status='S', text=_(u'Successfully sent asynchronous mdn to partner')) except Exception, e: models.Log.objects.create( message=pending_mdn.omessage, status='E', text=_( u'Failed to send asynchronous mdn to partner, error is {0:s}' .format(e))) finally:
def patch_to_mbox(patch): postscript_re = re.compile('\n-{2,3} ?\n') comment = None try: comment = Comment.objects.get(patch=patch, msgid=patch.msgid) except Exception: pass body = '' if comment: body = comment.content.strip() + "\n" parts = postscript_re.split(body, 1) if len(parts) == 2: (body, postscript) = parts body = body.strip() + "\n" postscript = postscript.rstrip() else: postscript = '' for comment in Comment.objects.filter(patch=patch) \ .exclude(msgid=patch.msgid): body += comment.patch_responses() if postscript: body += '---\n' + postscript + '\n' if patch.content: body += '\n' + patch.content delta = patch.date - datetime.datetime.utcfromtimestamp(0) utc_timestamp = delta.seconds + delta.days * 24 * 3600 mail = PatchMbox(body) mail['Subject'] = patch.name mail['From'] = email.utils.formataddr( (str(Header(patch.submitter.name, mail.patch_charset)), patch.submitter.email)) mail['X-Patchwork-Id'] = str(patch.id) if patch.delegate: mail['X-Patchwork-Delegate'] = str(patch.delegate.email) mail['Message-Id'] = patch.msgid mail.set_unixfrom('From patchwork ' + patch.date.ctime()) copied_headers = ['To', 'Cc', 'Date'] orig_headers = HeaderParser().parsestr(str(patch.headers)) for header in copied_headers: if header in orig_headers: mail[header] = orig_headers[header] if 'Date' not in mail: mail['Date'] = email.utils.formatdate(utc_timestamp) return mail