def get_mails(self): try: self.__connect() except ImapBoxConnectionError: raise ImapBoxConnectionError() except ImapBoxAuthError: raise ImapBoxAuthError() mails = [] try: if self.use_default_mbox: result, message = self.mbox.select(readonly=1) else: result, message = self.mbox.select(self.mbox_dir, readonly=1) if result != 'OK': raise Exception, message # retrieve only unseen messages typ, data = self.mbox.search(None, 'UNSEEN') for num in data[0].split(): # fetch only needed fields f = self.mbox.fetch(num, '(BODY.PEEK[HEADER.FIELDS (SUBJECT FROM MESSAGE-ID)])') hp = HeaderParser() m = hp.parsestr(f[1][0][1]) sub = utils.mime_decode(m['subject']) fr = utils.mime_decode(m['from']) mails.append([m['Message-ID'], sub, fr]) except Exception, e: print str(e)
def getmail(user, password, gmailfolder): conn = imaplib.IMAP4_SSL("imap.gmail.com", 993) conn.login(user, password) conn.select(gmailfolder) # mailbox/gmail label # print conn.status(gmailfolder,"(MESSAGES)")#print message count since = datetime.datetime.today() - datetime.timedelta(days=90) since = since.strftime("%d-%b-%Y") dates = [] typ, mailnumlist = conn.search(None, "SINCE", since) # or ALL typ, mailheaders = conn.fetch(mailnumlist[0].replace(" ", ","), "(BODY.PEEK[HEADER])") for response_part in mailheaders: if isinstance(response_part, tuple): header_data = response_part[1] headerparser = HeaderParser() msg = headerparser.parsestr(header_data) # Convert long form date into UTC timestamp while considering tz msgdatetimestamp = parsedate_tz(msg["Date"]) # Discard hours/minutes/seconds as we are aggregating by whole dates msgdate = msgdatetimestamp[0:3] + (0, 0, 0, 0, 0, 0, 0, -18000) # Format cleanly for output as Javascript timestamp dates.append(str(int(mktime_tz(msgdate)))) conn.close() datesdict = {} output = "" alldates = [key for key, _ in groupby(dates)] for i in alldates: datesdict[i] = dates.count(i) output += '{ "label": "Email", \n' output += ' "data": [\n' for k, v in sorted(datesdict.items()): output += " [%s, %s],\n" % (k, v) output = output[:-2] + "\n]}" return output
def get_mails(self): try: self.__connect() except ImapBoxConnectionError: raise ImapBoxConnectionError() except ImapBoxAuthError: raise ImapBoxAuthError() mails = [] try: if self.use_default_mbox: result, message = self.mbox.select(readonly=1) else: result, message = self.mbox.select(self.mbox_dir, readonly=1) if result != 'OK': raise Exception, message # retrieve only unseen messages typ, data = self.mbox.search(None, 'UNSEEN') for num in data[0].split(): # fetch only needed fields f = self.mbox.fetch( num, '(BODY.PEEK[HEADER.FIELDS (SUBJECT FROM MESSAGE-ID)])') hp = HeaderParser() m = hp.parsestr(f[1][0][1]) sub = utils.mime_decode(m['subject']) fr = utils.mime_decode(m['from']) mails.append([m['Message-ID'], sub, fr]) except Exception, e: print str(e)
def processRedirect(self, code, match, end): # TODO: detect redirect loops # TODO: permanently change URL on 301? if code not in ['301', '302', '303', '307']: return False parser = HeaderParser() message = parser.parsestr(self.readHeaders[match.end():end], True) if 'Location' not in message: return False location = message['Location'] self.socket.close() self.__init__(location,self.proxy,self.rawServer,self.callback,self.args,self.kwargs) self.get() return True
def processResponse(self, end): match = STATUS_RE.match(self.readHeaders) if not match: self.reportFailure('Invalid response') return code, reason = match.groups() if code != '200': if not self.processRedirect(code, match, end): self.reportFailure('Bad response: %s %s' % (code, reason)) return parser = HeaderParser() message = parser.parsestr(self.readHeaders[match.end():end], True) if not self.callback(CONNECT, message, *self.args, **self.kwargs): self.socket.close() return data = self.readHeaders[end:] self.readHeaders = None # TODO: Error on unknown transfer-encoding if 'Transfer-Encoding' in message and \ message['Transfer-Encoding'] == 'chunked': self.chunkSize = 0 self.sendData(data)
def parse_docstring(docstring): """ Parse out the parts of a docstring. Returns (title, body, metadata). """ docstring = trim_docstring(docstring) parts = re.split(r'\n{2,}', docstring) title = parts[0] if len(parts) == 1: body = '' metadata = {} else: parser = HeaderParser() try: metadata = parser.parsestr(parts[-1]) except HeaderParseError: metadata = {} body = "\n\n".join(parts[1:]) else: metadata = dict(list(metadata.items())) if metadata: body = "\n\n".join(parts[1:-1]) else: body = "\n\n".join(parts[1:]) return title, body, metadata
def parse_docstring(docstring): """ Parse out the parts of a docstring. Returns (title, body, metadata). """ docstring = trim_docstring(docstring) parts = re.split(r'\n{2,}', docstring) title = parts[0] if len(parts) == 1: body = '' metadata = {} else: parser = HeaderParser() try: metadata = parser.parsestr(parts[-1]) except HeaderParseError: metadata = {} body = "\n\n".join(parts[1:]) else: metadata = dict(metadata.items()) if metadata: body = "\n\n".join(parts[1:-1]) else: body = "\n\n".join(parts[1:]) return title, body, metadata
def verpdeliver(mlist, msg, msgdata, envsender, failures, conn): for recip in msgdata['recips']: # We now need to stitch together the message with its header and # footer. If we're VERPIng, we have to calculate the envelope sender # for each recipient. Note that the list of recipients must be of # length 1. # # BAW: ezmlm includes the message number in the envelope, used when # sending a notification to the user telling her how many messages # they missed due to bouncing. Neat idea. msgdata['recips'] = [recip] # Make a copy of the message and decorate + delivery that msgcopy = copy.deepcopy(msg) Decorate.process(mlist, msgcopy, msgdata) # Calculate the envelope sender, which we may be VERPing if msgdata.get('verp'): bmailbox, bdomain = Utils.ParseEmail(envsender) rmailbox, rdomain = Utils.ParseEmail(recip) if rdomain is None: # The recipient address is not fully-qualified. We can't # deliver it to this person, nor can we craft a valid verp # header. I don't think there's much we can do except ignore # this recipient. syslog('smtp', 'Skipping VERP delivery to unqual recip: %s', recip) continue d = {'bounces': bmailbox, 'mailbox': rmailbox, 'host' : DOT.join(rdomain), } envsender = '%s@%s' % ((mm_cfg.VERP_FORMAT % d), DOT.join(bdomain)) if mlist.personalize == 2: # When fully personalizing, we want the To address to point to the # recipient, not to the mailing list del msgcopy['to'] name = None if mlist.isMember(recip): name = mlist.getMemberName(recip) if name: # Convert the name to an email-safe representation. If the # name is a byte string, convert it first to Unicode, given # the character set of the member's language, replacing bad # characters for which we can do nothing about. Once we have # the name as Unicode, we can create a Header instance for it # so that it's properly encoded for email transport. charset = Utils.GetCharSet(mlist.getMemberLanguage(recip)) if charset == 'us-ascii': # Since Header already tries both us-ascii and utf-8, # let's add something a bit more useful. charset = 'iso-8859-1' charset = Charset(charset) codec = charset.input_codec or 'ascii' if not isinstance(name, UnicodeType): name = unicode(name, codec, 'replace') name = Header(name, charset).encode() msgcopy['To'] = formataddr((name, recip)) else: msgcopy['To'] = recip # We can flag the mail as a duplicate for each member, if they've # already received this message, as calculated by Message-ID. See # AvoidDuplicates.py for details. del msgcopy['x-mailman-copy'] if msgdata.get('add-dup-header', {}).has_key(recip): msgcopy['X-Mailman-Copy'] = 'yes' # GPG encryption if 'encrypted_gpg' in msgdata and msgdata['encrypted_gpg'] and mlist.encrypt_policy!=0: # Encryption is not forbidden in config try: keyids=mlist.getGPGKeyIDs(recip) except: keyids=None if enforceEncryptPolicy(mlist,msg,msgdata) and keyids==None: syslog('gpg','Encryption mandatory, but no keys found for %s: '\ 'Discarding message',recip) failures[recip]=(550,'Encryption mandatory, but no keys found') return gh = GPGUtils.GPGHelper(mlist) # Extract / generate plaintext gpg_use_inlineformat = False # TODO: Create config setting if not msgcopy.is_multipart() and gpg_use_inlineformat: plaintext=msgcopy.get_payload() else: if not msgcopy.is_multipart(): plaintext = 'Content-Type: %s\n' \ 'Content-Disposition: inline\n' \ % msgcopy.get('Content-Type') if not msgcopy.get('Content-Transfer-Encoding') is None: plaintext += 'Content-Transfer-Encoding: %s\n' \ % msgcopy.get('Content-Transfer-Encoding') plaintext += '\n%s' % msgcopy.get_payload() else: hp = HeaderParser() tmp = msgcopy.as_string() tmpmsg = hp.parsestr(tmp) plaintext = 'Content-Type: %s\n' \ 'Content-Disposition: inline\n\n%s' \ % (msgcopy.get('Content-Type'),tmpmsg.get_payload()) # Do encryption, report errors ciphertext = None if not keyids is None: # Can encrypt. # No signing policy, or voluntary and original wasn't signed: just encrypt if mlist.sign_policy == 0 or \ (mlist.sign_policy==1 and not msgdata['signed_gpg']): ciphertext = gh.encryptMessage(plaintext,keyids) else: ciphertext = gh.encryptSignMessage(plaintext,keyids) if ciphertext==None: # Must always encrypt, since if we arrived here encrypt_policy # is either Mantatory or (Voluntary and incoming msg was encrypted). syslog('gpg',"Can't encrypt message to %s: " \ "Discarding message",keyids) failures[recip]=(550,'Unable to encrypt message') return # Compile encrypted message if not ciphertext is None: if msgcopy.has_key('Content-Transfer-Encoding'): msgcopy.replace_header('Content-Transfer-Encoding','7bit') else: msgcopy.add_header('Content-Transfer-Encoding','7bit') if not msgcopy.is_multipart() and gpg_use_inlineformat: msgcopy.set_payload(ciphertext) msgcopy.set_param('x-action','pgp-encrypted') else: msgcopy.replace_header('Content-Type','multipart/encrypted') msgcopy.set_param('protocol','application/pgp-encrypted') msgcopy.set_payload(None) submsg = Message() submsg.add_header('Content-Type','application/pgp-encrypted') submsg.set_payload('Version: 1\n') msgcopy.attach(submsg) submsg = Message() submsg.add_header('Content-Type','application/octet-stream; name="encrypted.asc"') submsg.add_header('Content-Disposition','inline; filename="encrypted.asc"') submsg.set_payload(ciphertext) msgcopy.attach(submsg) syslog('gpg','Sending encrypted message to %s',recip) else: syslog('gpg','Sending unencrypted message to %s',recip) if 'encrypted_smime' in msgdata and msgdata['encrypted_smime'] and mlist.encrypt_policy != 0: # FIXME: this is as crude as can be sm = SMIMEUtils.SMIMEHelper(mlist) recipfile = sm.getSMIMEMemberCertFile(recip) if not recipfile: failures[recip]=(550,'No S/MIME key found') return else: plaintext=msgcopy.get_payload() if not msgcopy.is_multipart(): plaintext = msgcopy.get_payload() syslog('gpg', "About to S/MIME encrypt plaintext from singlepart") else: # message contains e.g. signature? # FIXME we fetch only the first attachment. We search for # attachments only 2 levels deep. That's suboptimal... # perhaps the PGP way (invoking # hp = HeaderParser() # ) is better. submsgs = msgcopy.get_payload() submsg = submsgs[0] if not submsg.is_multipart(): plaintext = submsg.get_payload() else: subsubmsgs = submsg.get_payload() subsubmsg = subsubmsgs[0] plaintext = subsubmsg.get_payload() syslog('gpg', "About to S/MIME encrypt plaintext from multipart") if mlist.sign_policy == 0 or \ (mlist.sign_policy==1 and not msgdata['signed_smime']): ciphertext = sm.encryptMessage(plaintext,recipfile) else: ciphertext = sm.encryptSignMessage(plaintext,recipfile) # deal with both header and body-part of ciphertext (header, body) = ciphertext.split("\n\n", 1) for l in header.split("\n"): (k, v) = l.split(": ", 1) # behave sane with borken openssl like 0.9.7e (e.g. Debian's 0.9.7e-3sarge1) # openssl 0.9.8a-4a0.sarge.1 is known to work OK. # A borken openssl (and therefore sm.encryptMessage) returns # Content-Type: application/x-pkcs7-mime; name="smime.p7m" # while we need a # Content-Type: application/x-pkcs7-mime; smime-type=enveloped-data; name="smime.p7m" if v == 'application/x-pkcs7-mime; name="smime.p7m"': v = 'application/x-pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"' try: msgcopy.replace_header(k, v) except KeyError: msgcopy.add_header(k, v) msgcopy.set_payload(body) # For the final delivery stage, we can just bulk deliver to a party of # one. ;) bulkdeliver(mlist, msgcopy, msgdata, envsender, failures, conn)