help = 'send a patch or series of patches by e-mail'
-usage = """%prog [options]"""
-
-options = [make_option('-t', '--template', metavar = 'FILE',
- help = 'use FILE as the message template'),
+usage = """%prog [options] [<patch>]
+
+Send a patch or a range of patches (defaulting to the applied patches)
+by e-mail using the 'smtpserver' configuration option. The From/To/Cc
+addresses and the e-mail format are generated from the template file
+passed as argument to '--template' (defaulting to
+.git/patchmail.tmpl). A preamble e-mail can also be sent using the
+'--first' option (no default template).
+
+All the subsequent e-mails appear as replies to the first e-mail sent
+(either the preamble or the first patch). E-mails can be seen as
+replies to a different e-mail by using the '--refid' option.
+
+SMTP authentication is also possible with '--smtp-user' and
+'--smtp-password' options, also available as configuration settings:
+'smtpuser' and 'smtppassword'.
+
+The template e-mail headers and body must be separated by
+'%(endofheaders)s' variable, which is replaced by StGIT with
+additional headers and a blank line. The patch e-mail template accepts
+the following variables:
+
+ %(patch)s - patch name
+ %(shortdescr)s - the first line of the patch description
+ %(longdescr)s - the rest of the patch description, after the first line
+ %(endofheaders)s - delimiter between e-mail headers and body
+ %(diff)s - unified diff of the patch
+ %(diffstat)s - diff statistics
+ %(date)s - current date/time
+ %(patchnr)s - patch number
+ %(totalnr)s - total number of patches to be sent
+ %(authname)s - author's name
+ %(authemail)s - author's email
+ %(authdate)s - patch creation date
+ %(commname)s - committer's name
+ %(commemail)s - committer's e-mail
+
+For the preamble e-mail template, only the %(date)s, %(endofheaders)s
+and %(totalnr)s variables are supported."""
+
+options = [make_option('-a', '--all',
+ help = 'e-mail all the applied patches',
+ action = 'store_true'),
make_option('-r', '--range',
metavar = '[PATCH1][:[PATCH2]]',
help = 'e-mail patches between PATCH1 and PATCH2'),
+ make_option('-t', '--template', metavar = 'FILE',
+ help = 'use FILE as the message template'),
make_option('-f', '--first', metavar = 'FILE',
help = 'send FILE as the first message'),
make_option('-s', '--sleep', type = 'int', metavar = 'SECONDS',
help = 'sleep for SECONDS between e-mails sending'),
make_option('--refid',
- help = 'Use REFID as the reference id')]
+ help = 'Use REFID as the reference id'),
+ make_option('-u', '--smtp-user', metavar = 'USER',
+ help = 'username for SMTP authentication'),
+ make_option('-p', '--smtp-password', metavar = 'PASSWORD',
+ help = 'username for SMTP authentication')]
def __parse_addresses(string):
return (from_addr_list[0], to_addr_list)
-def __send_message(smtpserver, from_addr, to_addr_list, msg, sleep):
+def __send_message(smtpserver, from_addr, to_addr_list, msg, sleep,
+ smtpuser, smtppassword):
"""Send the message using the given SMTP server
"""
try:
s.set_debuglevel(0)
try:
+ if smtpuser and smtppassword:
+ s.ehlo()
+ s.login(smtpuser, smtppassword)
+
s.sendmail(from_addr, to_addr_list, msg)
# give recipients a chance of receiving patches in the correct order
time.sleep(sleep)
"""Send the patches by e-mail using the patchmail.tmpl file as
a template
"""
- if len(args) != 0:
+ if len(args) > 1:
parser.error('incorrect number of arguments')
if not config.has_option('stgit', 'smtpserver'):
raise CmdException, 'smtpserver not defined'
smtpserver = config.get('stgit', 'smtpserver')
+ smtpuser = None
+ smtppassword = None
+ if config.has_option('stgit', 'smtpuser'):
+ smtpuser = config.get('stgit', 'smtpuser')
+ if config.has_option('stgit', 'smtppassword'):
+ smtppassword = config.get('stgit', 'smtppassword')
+
applied = crt_series.get_applied()
- if options.range:
+ if len(args) == 1:
+ if args[0] in applied:
+ patches = [args[0]]
+ else:
+ raise CmdException, 'Patch "%s" not applied' % args[0]
+ elif options.all:
+ patches = applied
+ elif options.range:
boundaries = options.range.split(':')
if len(boundaries) == 1:
start = boundaries[0]
if start_idx >= stop_idx:
raise CmdException, 'Incorrect patch range order'
+
+ patches = applied[start_idx:stop_idx]
else:
- start_idx = 0
- stop_idx = len(applied)
+ raise CmdException, 'Incorrect options. Unknown patches to send'
+
+ if options.smtp_password:
+ smtppassword = options.smtp_password
+
+ if options.smtp_user:
+ smtpuser = options.smtp_user
+
+ if (smtppassword and not smtpuser):
+ raise CmdException, 'SMTP password supplied, username needed'
+ if (smtpuser and not smtppassword):
+ raise CmdException, 'SMTP username supplied, password needed'
- patches = applied[start_idx:stop_idx]
total_nr = len(patches)
+ if total_nr == 0:
+ raise CmdException, 'No patches to send'
ref_id = options.refid
print 'Sending file "%s"...' % options.first,
sys.stdout.flush()
- __send_message(smtpserver, from_addr, to_addr_list, msg, sleep)
+ __send_message(smtpserver, from_addr, to_addr_list, msg, sleep,
+ smtpuser, smtppassword)
print 'done'
print 'Sending patch "%s"...' % p,
sys.stdout.flush()
- __send_message(smtpserver, from_addr, to_addr_list, msg, sleep)
+ __send_message(smtpserver, from_addr, to_addr_list, msg, sleep,
+ smtpuser, smtppassword)
print 'done'