def get_message(self, key): """Return a Message representation or raise a KeyError.""" with self._get_fd(key) as fd: if self._factory: return self._factory(fd) else: return mailbox.MaildirMessage(fd)
def store(self, message, folder): box = self.__mailbox(folder) msg = mailbox.MaildirMessage(message) key = box.add(msg) self.index[self.digest(message)] = folder + "/" + key self.log(INFO, f"stored {key}") return key
def _save_local_message_copy(msg, person, assignment_path, dry_run=False): try: _os.makedirs(assignment_path) except OSError: pass mpath = _os_path.join(assignment_path, 'mail') try: mbox = _mailbox.Maildir(mpath, factory=None, create=not dry_run) except _mailbox.NoSuchMailboxError as e: _LOG.warn('could not open mailbox at {}'.format(mpath)) mbox = None new_msg = True else: new_msg = True for other_msg in mbox: if other_msg['Message-ID'] == msg['Message-ID']: new_msg = False break if new_msg: _LOG.log(_GOOD_DEBUG, 'saving email from {} to {}'.format(person, assignment_path)) if mbox is not None and not dry_run: mdmsg = _mailbox.MaildirMessage(msg) mdmsg.add_flag('S') mbox.add(mdmsg) mbox.close() else: _LOG.log(_GOOD_DEBUG, 'already found {} in {}'.format(msg['Message-ID'], mpath))
def convert(self, outpath): box = mailbox.Maildir(outpath) for jconversation in self.jfile['conversations']: conv_messages = [] first_id = None for jmsg in jconversation: msg = self.build_message(jmsg) if self.options.threading: # create a fake empty root message for each conversation if first_id is None: if 'address' in jmsg: # sms root = self.build_fake_root([jmsg['address']]) elif 'addresses' in jmsg: root = self.build_fake_root(jmsg['addresses']) else: raise NotImplementedError( 'no address in the first message') # conv_messages.append(root) first_id = root['Message-ID'] set_header(msg, 'References', first_id) msg = mailbox.MaildirMessage(msg) if jmsg.get('read', False): msg.add_flag('S') conv_messages.append(msg) for msg in conv_messages: box.add(msg)
def format_email(to=None, ffrom=None, date=None, subject=None, body=None, msgObject=None): """ contains maildir-specific extensions... """ if not msgObject: msgObject = mailbox.MaildirMessage() msgObject['Message-Id'] = email.utils.make_msgid() msgObject.set_payload(body) for X in ['Subject', 'To', 'From', 'Date']: # otherwise we'll add multiple values del msgObject[X] msgObject['Subject'] = subject msgObject['To'] = to if ffrom: msgObject['From'] = ffrom else: msgObject['From'] = addressbook.utils.my_address().email if date: msgObject['Date'] = date else: msgObject['Date'] = email.utils.formatdate() msgObject.set_flags('S') msgObject.set_subdir('cur') return msgObject
def create_mail(msg, maildir, notmuch_db, tags, old=False): email_message = email.message.EmailMessage() # freezegun doesn't handle time zones properly when generating UNIX # timestamps. When the local timezone is UTC+2, the generated timestamp # is 2 hours ahead of what it should be. Due to this we need to make sure # that the dates are always sufficiently far behind 2019-01-30 12:00 to # handle up to UTC+12 . if old: email_message['Date'] = 'Wed, 10 Jan 2019 13:00:00 +0100' else: email_message['Date'] = 'Wed, 20 Jan 2019 13:00:00 +0100' email_message['From'] = 'You <*****@*****.**>' email_message['To'] = 'Me <*****@*****.**>' email_message['Message-ID'] = make_msgid() email_message.set_content(msg) maildir_message = mailbox.MaildirMessage(email_message) message_key = maildir.add(maildir_message) fname = os.path.join(maildir._path, maildir._lookup(message_key)) notmuch_msg = notmuch_db.add_message(fname) for tag in tags: notmuch_msg.add_tag(tag, False) # Remove the angle brackets automatically added around the message ID by make_msgid. stripped_msgid = email_message['Message-ID'].strip('<>') return (stripped_msgid, msg)
def sample_mail(subject="Sample subject"): msg = mailbox.MaildirMessage() msg.set_unixfrom('author Sat Jan 01 15:35:34 2019') msg['From'] = "from@localhost" msg['To'] = "to@localhost" msg['Subject'] = subject msg['Date'] = email.utils.formatdate() msg.set_payload("Sample body") return msg
def get_message(self, key): """Return a Message representation or raise a KeyError.""" fd = self._get_fd(key) try: if self._factory: return self._factory(fd) else: return mailbox.MaildirMessage(fd) finally: fd.close()
def process_message(request_id, response, exception): if exception is not None: print("ERROR: " + request_id) else: msg_bytes = base64.urlsafe_b64decode(response['raw'].encode('ASCII')) mime_msg = email.message_from_bytes(msg_bytes) maildir_message = mailbox.MaildirMessage(mime_msg) #box.add(maildir_message) message_id = response['id'] with open("mail/cur/%s" % message_id, "wb") as message_file: message_file.write(maildir_message.__bytes__())
def add(self, msg, folder, flags): """ add message in a given subdir """ mmsg = mailbox.MaildirMessage(msg) if GMVaultExporter.GM_SEEN in flags: mmsg.set_subdir('cur') mmsg.add_flag('S') if mmsg.get_subdir() == 'cur' and GMVaultExporter.GM_FLAGGED in flags: mmsg.add_flag('F') self.subdir(folder).add(mmsg)
def deliver_maildir(self,suspect): md_msg=mailbox.MaildirMessage(suspect.get_message_rep()) md_path=apply_template(self.config.get(self.section,'path'), suspect) if os.path.isfile(md_path): self.logger.error("%s seems to be a file - can not use as maildir"%md_path) return maildir=mailbox.Maildir(md_path) try: maildir.lock() maildir.add(md_msg) maildir.flush() except Exception,e: self.logger.error("Could not store message %s to %s: %s"%(suspect.id,md_path,str(e)))
def test___getitem___valid_message_id_w_datestamp_folder_w_message(self): import os import mailbox path = self._getTempdir() root = mailbox.Maildir(os.path.join(path, 'Maildir'), factory=None, create=True) root.add_folder('2009.06.23') folder = root.get_folder('2009.06.23') to_store = mailbox.MaildirMessage('STORE_ME') key = folder.add(to_store) md = self._makeOne(path) md.sql.execute('insert into messages' '(message_id, year, month, day, maildir_key)' ' values("ABC", 2009, 6, 23, "%s")' % key) message = md['ABC'] # doesn't raise
def _add_message(self, maildir, msg_id, flags, subdir): m = mailbox.MaildirMessage() m.set_payload('Hello world!', 'ascii') m.add_header('from', '*****@*****.**') m.add_header('to', '*****@*****.**') m.add_header('subject', 'Hi!') m.add_header('message-id', msg_id) if flags: m.set_flags(flags) m.set_subdir(subdir) maildir.lock() try: maildir.add(m) finally: maildir.unlock()
def deliver( self, subject='Test mail', body='This is a test mail', to='*****@*****.**', frm='*****@*****.**', headers=None, new=False, # Move to new dir or cur dir? keywords=None, # List of keywords or labels seen=False, # Seen flag (cur dir only) replied=False, # Replied flag (cur dir only) flagged=False): # Flagged flag (cur dir only) """Deliver a new mail message in the mbox. This does only adds the message to maildir, does not insert it into the notmuch database. :returns: A tuple of (msgid, pathname). """ msgid = self._next_msgid() when = time.time() msg = email.message.EmailMessage() msg.add_header('Received', 'by MailDir; {}'.format(time.ctime(when))) msg.add_header('Message-ID', '<{}>'.format(msgid)) msg.add_header('Date', time.ctime(when)) msg.add_header('From', frm) msg.add_header('To', to) msg.add_header('Subject', subject) if headers: for h, v in headers: msg.add_header(h, v) msg.set_content(body) mdmsg = mailbox.MaildirMessage(msg) if not new: mdmsg.set_subdir('cur') if flagged: mdmsg.add_flag('F') if replied: mdmsg.add_flag('R') if seen: mdmsg.add_flag('S') boxid = self.mailbox.add(mdmsg) basename = boxid if mdmsg.get_info(): basename += mailbox.Maildir.colon + mdmsg.get_info() msgpath = self.path / mdmsg.get_subdir() / basename return (msgid, msgpath)
def store_mail(mbx, mail): """ stores given mail in mailbox. If mailbox is maildir, set the S-flag and return path to newly added mail. Oherwise this will return `None`. :param mbx: mailbox to use :type mbx: :class:`mailbox.Mailbox` :param mail: the mail to store :type mail: :class:`email.message.Message` or str :returns: absolute path of mail-file for Maildir or None if mail was successfully stored :rtype: str or None :raises: StoreMailError """ if not isinstance(mbx, mailbox.Mailbox): logging.debug('Not a mailbox') return False mbx.lock() if isinstance(mbx, mailbox.Maildir): logging.debug('Maildir') msg = mailbox.MaildirMessage(mail) msg.set_flags('S') else: logging.debug('no Maildir') msg = mailbox.Message(mail) try: message_id = mbx.add(msg) mbx.flush() mbx.unlock() logging.debug('got mailbox msg id : %s', message_id) except Exception as e: raise StoreMailError(e) path = None # add new Maildir message to index and add tags if isinstance(mbx, mailbox.Maildir): # this is a dirty hack to get the path to the newly added file # I wish the mailbox module were more helpful... plist = glob.glob1(os.path.join(mbx._path, 'new'), message_id + '*') if plist: path = os.path.join(mbx._path, 'new', plist[0]) logging.debug('path of saved msg: %s', path) return path
def __setitem__(self, message_id, message): """ See IMessageStore. """ to_store = mailbox.MaildirMessage(message) date = to_store['Date'] yy, mm, dd, hh, mt, ss, wd, jd, dst = parsedate(date) folder_name = self._getFolderName(yy, mm, dd) folder = self._getMaildir(folder_name) key = folder.add(to_store) try: self.sql.execute('insert into messages' '(message_id, year, month, day, maildir_key) ' 'values("%s", %d, %d, %d, "%s")' % (message_id, yy, mm, dd, key) ) except: folder.remove(key) raise
def _explain_to(self, message): """Copy format-specific state to message.""" if isinstance(message, mailbox.MaildirMessage): flag_map = { '\\draft': 'D', '\\flagged': 'F', '\\answered': 'R', '\\seen': 'S', '\\deleted': 'T' } msg.set_flags(v for k, v in flag_map.items() if k in self._flags) if '\\recent' not in self._flags: msg.set_subdir('cur') if self._idate is not None: msg.set_date(self._idate) else: # Use maildir conversion for all other formats maildir = mailbox.MaildirMessage(self) maildir._explain_to(message)
def make_message( self, subject='subject', from_addr='*****@*****.**', to_addr='*****@*****.**'): mbox = mailbox.Maildir(self._path) mbox.lock() try: msg = mailbox.MaildirMessage() msg.set_unixfrom('author Sat Jul 23 15:35:34 2017') msg['From'] = from_addr msg['To'] = to_addr msg['Subject'] = subject msg['Date'] = email.utils.formatdate() msg.set_payload(textwrap.dedent(''' This is the body. There are 2 lines. ''')) mbox.add(msg) mbox.flush() finally: mbox.unlock() return msg
def main(argv): in_mbox = "inbox.mbox" out_box = "Maildir" try: opts, args = getopt.getopt(argv, "i:o:", ["infile=", "outdir="]) except getopt.GetoptError: print("python splitgmail.py -i <infile> -o <outdir>") sys.exit(2) for opt, arg in opts: if opt in ("-i", "--infile"): in_mbox = arg elif opt in ("-o", "--outdir"): out_box = arg print("Processing file \"" + in_mbox + "\", output \"" + out_box + "\"") sys.stdout.flush() destMbox = mailbox.Maildir(out_box, create=True) # create common subfolders, INBOX is root destMbox.add_folder("Sent") destMbox.add_folder("Archive") sourcembox = mailbox.mbox(in_mbox, create=False) print(str(sourcembox.__len__()) + " messages to process") sys.stdout.flush() mcount = mjunk = mchat = msaved = 0 for message in sourcembox: read = True flagged = False mcount += 1 gmail_labels = message["X-Gmail-Labels"] # extract delivery date from mbox "From_" field ddate = message.get_from() ddate = ddate.split(' ', 1)[1] depoch = time.mktime( time.strptime(ddate.strip(), "%a %b %d %H:%M:%S +0000 %Y")) - time.timezone tbox = "Archive" # default target box: Archive if gmail_labels: gmail_labels = gmail_labels.split( ',' ) # from here we only work on an array to avoid partial matches if "Unread" in gmail_labels: read = False if "Starred" in gmail_labels: flagged = True if "Spam" in gmail_labels: # skip all spam mjunk += 1 continue elif "Chat" in gmail_labels: # skip all chat mchat += 1 continue elif "Sent" in gmail_labels: # anything that has Sent goes to Sent box tbox = "Sent" elif "Inbox" in gmail_labels: # Inbox treated here because some messages can be Sent,Inbox tbox = "Inbox" else: for label in gmail_labels: # ignore meta labels if label == "Important" or label == "Unread" or label == "Starred" or label == "Newsletters": continue # use first match tbox = label # handle odd labels if label == "[Imap]/Archive": tbox = "Archive" break # if nothing matched we'll use default set at message loop start # fixup missing status flags in the message if read: message["Status"] = "RO" else: message["Status"] = "O" if flagged: message["X-Status"] = "F" mfrom = message["From"] or "Unknown" mid = message["Message-Id"] or "<N/A>" print("Storing " + mid + " from \"" + mfrom + "\" to folder \"" + tbox + "\"") msaved += 1 # convert message to maildir MDmsg = mailbox.MaildirMessage(message) # fixup received date MDmsg.set_date(depoch) if tbox == "Inbox": destMbox.add(MDmsg) else: if tbox not in destMbox.list_folders(): destMbox.add_folder(tbox) tfolder = destMbox.get_folder(tbox) tfolder.add(MDmsg) print( str(mcount) + " messages processed, " + str(saved) + " messages saved") print("ignored: " + str(mjunk) + " spam, " + str(mchat) + " mchat")
def deliver(self, message): # TODO: Create an ID based on process and thread IDs. # Current bhaviour may allow for name clashes in multi-threaded. self.box.add(mailbox.MaildirMessage(str(message)))
def iadd(ui, repo, id=None, comment=0, **opts): """Adds a new issue, or comment to an existing issue ID or its comment COMMENT""" comment = int(comment) # First, make sure issues have a directory issues_dir = ui.config('artemis', 'issues', default=default_issues_dir) issues_path = os.path.join(repo.root, issues_dir) if not os.path.exists(issues_path): os.mkdir(issues_path) if id: issue_fn, issue_id = _find_issue(ui, repo, id) if not issue_fn: ui.warn('No such issue\n') return _create_missing_dirs(issues_path, issue_id) mbox = mailbox.Maildir(issue_fn, factory=mailbox.MaildirMessage) keys = _order_keys_date(mbox) root = keys[0] user = ui.username() default_issue_text = "From: %s\nDate: %s\n" % (user, datestr(format=date_format)) if not id: default_issue_text += "State: %s\n" % default_state default_issue_text += "Subject: brief description\n\n" else: subject = mbox[(comment < len(mbox) and keys[comment]) or root]['Subject'] if not subject.startswith('Re: '): subject = 'Re: ' + subject default_issue_text += "Subject: %s\n\n" % subject default_issue_text += "Detailed description." # Get properties, and figure out if we need an explicit comment properties = _get_properties(opts['property']) no_comment = id and properties and opts['no_property_comment'] message = opts['message'] # Create the text if message: if not id: state_str = 'State: %s\n' % default_state else: state_str = '' issue = "From: %s\nDate: %s\nSubject: %s\n%s" % \ (user, datestr(format=date_format), message, state_str) elif not no_comment: issue = ui.edit(default_issue_text, user) if issue.strip() == '': ui.warn('Empty issue, ignoring\n') return if issue.strip() == default_issue_text: ui.warn('Unchanged issue text, ignoring\n') return else: # Write down a comment about updated properties properties_subject = ', '.join( ['%s=%s' % (property, value) for (property, value) in properties]) issue = "From: %s\nDate: %s\nSubject: changed properties (%s)\n" % \ (user, datestr(format = date_format), properties_subject) # Create the message msg = mailbox.MaildirMessage(issue) if opts['attach']: outer = _attach_files(msg, opts['attach']) else: outer = msg # Pick random filename if not id: issue_fn = issues_path while os.path.exists(issue_fn): issue_id = _random_id() issue_fn = os.path.join(issues_path, issue_id) mbox = mailbox.Maildir(issue_fn, factory=mailbox.MaildirMessage) keys = _order_keys_date(mbox) # else: issue_fn already set # Add message to the mailbox mbox.lock() if id and comment >= len(mbox): ui.warn( 'No such comment number in mailbox, commenting on the issue itself\n' ) if not id: outer.add_header( 'Message-Id', "<%s-0-artemis@%s>" % (issue_id, socket.gethostname())) else: root = keys[0] outer.add_header( 'Message-Id', "<%s-%s-artemis@%s>" % (issue_id, _random_id(), socket.gethostname())) outer.add_header( 'References', mbox[(comment < len(mbox) and keys[comment]) or root]['Message-Id']) outer.add_header( 'In-Reply-To', mbox[(comment < len(mbox) and keys[comment]) or root]['Message-Id']) new_bug_path = issue_fn + '/new/' + mbox.add(outer) commands.add(ui, repo, new_bug_path) # Fix properties in the root message if properties: root = _find_root_key(mbox) msg = mbox[root] for property, value in properties: if property in msg: msg.replace_header(property, value) else: msg.add_header(property, value) mbox[root] = msg mbox.close() if opts['commit']: commands.commit(ui, repo, issue_fn) # If adding issue, add the new mailbox to the repository if not id: ui.status('Added new issue %s\n' % issue_id) else: _show_mbox(ui, mbox, 0)
# Open the maildir for delivery try: inbox = mailbox.Maildir(maildir, None, config.get("dystill", "create_maildirs")) except mailbox.Error, message: print "Could not deliver the message to the specified mailbox." sys.exit(EX_TEMPFAIL) except mailbox.NoSuchMailboxError, message: print "Could not deliver the message to the specified mailbox." sys.exit(EX_TEMPFAIL) folders = inbox.list_folders() # Bring the message in message = mailbox.MaildirMessage(zemail) delivered = False exit = EX_OK # Mark as read if actions.__contains__("markasread"): message.add_flag("S") message.set_subdir("cur") # Flag if actions.__contains__("flag"): message.add_flag("F") # Delete if actions.__contains__("delete"): message.add_flag("S")
# We only want to extract the items that have been read and which are # not deleted c.execute('select title, author, feedurl, pubDate, content from' + ' rss_item where unread=0 and deleted=0') # for every line, we put a message in the right mailbox for line in c: header = u'<html><head></head><body>'.encode('utf-8') footer = u'</body></html>'.encode('utf-8') msg = MIMEText(header+line[4].encode('utf-8')+footer, 'html') msg['Subject'] = line[0].encode('utf-8') msg['From'] = line[1].encode('utf-8') msg['Date'] = email.utils.formatdate(float(line[3])) if line[2] in feed2mail.keys(): feed = feed2mail[line[2]] # If the maildir doesn't exist, we create it. if feed not in destination.list_folders(): print "maildir", feed, "doesn't exist: we create it !" maildir_feed = destination.add_folder(feed) else: maildir_feed = destination.get_folder(feed) # Add the message to the maildir and mark it unread: msg_in_feed = mailbox.MaildirMessage(msg) msg_in_feed.set_flags('S') msg_key = maildir_feed.add(msg_in_feed) else: print "Unknown Feed:",line[2] destination.close() exit(0)
def email_from_raw(raw): msg_bytes = base64.urlsafe_b64decode(raw.encode('ASCII')) mime_msg = email.message_from_bytes(msg_bytes) maildir_message = str(mailbox.MaildirMessage(mime_msg)) return maildir_message