X-Git-Url: https://git.distorted.org.uk/~mdw/stgit/blobdiff_plain/b4bddc068e5440e8b747329df4db841a14483d85..23a88c7d79f3cec8ff330304894c249090278052:/stgit/commands/mail.py diff --git a/stgit/commands/mail.py b/stgit/commands/mail.py index 8ecc8a5..0b3159b 100644 --- a/stgit/commands/mail.py +++ b/stgit/commands/mail.py @@ -26,19 +26,64 @@ from stgit.config import config 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] [] + +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): @@ -62,7 +107,8 @@ 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: @@ -72,6 +118,10 @@ def __send_message(smtpserver, from_addr, to_addr_list, msg, sleep): 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) @@ -158,16 +208,30 @@ def func(parser, options, args): """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] @@ -195,12 +259,25 @@ def func(parser, options, args): 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 @@ -223,7 +300,8 @@ def func(parser, options, args): 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' @@ -246,6 +324,7 @@ def func(parser, options, args): 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'