Skip to content

Instantly share code, notes, and snippets.

@sbeyer
Forked from Turin86/mbox_send.py
Last active January 2, 2016 01:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sbeyer/8230267 to your computer and use it in GitHub Desktop.
Save sbeyer/8230267 to your computer and use it in GitHub Desktop.
A Python script that (re-)sends all messages in mbox files with From/To/Cc/Bcc as specified in the messages headers
#!/usr/bin/env python
"""\
A command-line utility that can (re)send all messages in an mbox file
with options for controlling the rate at which they are sent, etc.
"""
# This script is based on a gist on github, see
# https://gist.github.com/sbeyer/8230267
#
# For the origin of the script see
# https://github.com/wojdyr/fityk/wiki/MigrationToGoogleGroups
import sys
import os
import time
import mailbox
import email
import smtplib
from copy import copy
from optparse import OptionParser, make_option
from getpass import getpass
# Set some defaults
defBcc = []
defChunkSize = 100
defChunkDelay = 30.0
defUser = None
defHost = 'localhost'
defPort = 25
defCount = -1
defStart = -1
# define the command line options
option_list = [
make_option('--add-bcc', action='append', metavar='ADDRESSES', dest='bccAddresses', default=defBcc,
help='Address that every mail should be sent to, additionally. May be repeated.'),
make_option('--host', dest='host', default=defHost,
help='Hostname where SMTP server is running. [default: %s]' % defHost),
make_option('--port', type='int', dest='port', default=defPort,
help='Port number to use for connecting to SMTP server. [default: %d]' % defPort),
make_option('--user', dest='user', default=defUser,
help='Username for SMTP server. (Will prompt for password.)'),
make_option('--chunk', type='int', dest='chunkSize', default=defChunkSize,
help='How many messages to send in each batch before pausing. [default: %d]' % defChunkSize),
make_option('--pause', type='float', dest='chunkDelay', default=defChunkDelay,
help='How many seconds to delay between chunks. [default: %f]' % defChunkDelay),
make_option('--count', type='int', dest='count', default=defCount,
help='How many messages to send before exiting the tool. [default: all messages in mbox]'),
make_option('--start', type='int', dest='start', default=defStart,
help='Which message number to start with. [default: where the tool left off the last time, or zero]'),
]
#---------------------------------------------------------------------------
def get_hwm(hwmfile):
if not os.path.exists(hwmfile):
return -1
hwm = int(open(hwmfile).read())
return hwm
def set_hwm(hwmfile, count):
f = open(hwmfile, 'w')
f.write(str(count))
f.close()
def addresses(string):
if string:
return [x[1] for x in email.utils.getaddresses([string])]
return []
def main(args):
if sys.version_info < (2,5):
print('Python 2.5 or better is required.')
sys.exit(1)
# Parse the command line args
parser = OptionParser(
usage='%prog [options] mbox_file(s)',
description=__doc__,
version='%prog 20140103',
option_list=option_list)
options, arguments = parser.parse_args(args)
if not arguments:
parser.error('At least one mbox file is required')
smtpPassword = None
if options.user:
smtpPassword = getpass() # implies using TLS
# process the mbox file(s)
for mboxfile in arguments:
print('Opening %s...' % mboxfile)
mbox = mailbox.mbox(mboxfile)
totalInMbox = len(mbox)
print('Total messages in mbox: %d' % totalInMbox)
hwmfile = mboxfile + '.hwm'
print('Storing last message processed in %s' % hwmfile)
start = get_hwm(hwmfile)
if options.start != -1:
start = options.start
start += 1
print('Starting with message #%d' % start)
totalSent = 0
current = start
# Outer loop continues until either the whole mbox or options.count
# messages have been sent,
while (current < totalInMbox and
(totalSent < options.count or options.count == -1)):
# Inner loop works one chunkSize number of messages at a time,
# pausing and reconnecting to the SMTP server for each chunk.
print('Connecting to SMTP(%s, %d)' % (options.host, options.port))
smtp = smtplib.SMTP(options.host, options.port)
if options.user: # use TLS
print('Logging in as %s' % options.user)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login(options.user, smtpPassword)
chunkSent = 0
while chunkSent < options.chunkSize:
msg = mbox[current]
print('Processing message %d: %s' % (current, msg['Subject']))
try:
# Here is where we actually send the message
fromAddress = addresses(msg['From'])[0]
toAddresses = copy(options.bccAddresses)
toAddresses += addresses(msg['To'])
toAddresses += addresses(msg['Cc'])
toAddresses += addresses(msg['Bcc'])
smtp.sendmail(fromAddress, toAddresses, msg.as_string())
set_hwm(hwmfile, current) # set new 'high water mark'
current += 1
totalSent += 1
chunkSent += 1
if (current >= totalInMbox or
(totalSent >= options.count and options.count != -1)):
break
except smtplib.SMTPServerDisconnected as e:
print('Error: %s' % str(e))
del smtp
print('Pausing for %f seconds...' % options.chunkDelay)
time.sleep(options.chunkDelay)
print('')
break
else:
smtp.quit()
del smtp
print('Pausing for %f seconds...' % options.chunkDelay)
time.sleep(options.chunkDelay)
print('')
print('Goodbye')
#---------------------------------------------------------------------------
if __name__ == '__main__':
main(sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment