author | Kirill Smelkov <kirr@mns.spb.ru> |
Wed, 23 Jan 2008 21:49:44 +0300 | |
changeset 5933 | 28a79c259fcf |
parent 5866 | dc6ed2736c81 |
child 5947 | 528c986f0162 |
permissions | -rw-r--r-- |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1 |
# mail.py - mail sending bits for mercurial |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
2 |
# |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
3 |
# Copyright 2006 Matt Mackall <mpm@selenic.com> |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
4 |
# |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
5 |
# This software may be used and distributed according to the terms |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
6 |
# of the GNU General Public License, incorporated herein by reference. |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
7 |
|
3891 | 8 |
from i18n import _ |
4096 | 9 |
import os, smtplib, templater, util, socket |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
10 |
|
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
11 |
def _smtp(ui): |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
12 |
'''send mail using smtp.''' |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
13 |
|
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
14 |
local_hostname = ui.config('smtp', 'local_hostname') |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
15 |
s = smtplib.SMTP(local_hostname=local_hostname) |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
16 |
mailhost = ui.config('smtp', 'host') |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
17 |
if not mailhost: |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
18 |
raise util.Abort(_('no [smtp]host in hgrc - cannot send mail')) |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
19 |
mailport = int(ui.config('smtp', 'port', 25)) |
2964
26c8d37496c2
fix typo in mail.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2929
diff
changeset
|
20 |
ui.note(_('sending mail: smtp host %s, port %s\n') % |
26c8d37496c2
fix typo in mail.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2929
diff
changeset
|
21 |
(mailhost, mailport)) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
22 |
s.connect(host=mailhost, port=mailport) |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
23 |
if ui.configbool('smtp', 'tls'): |
4093
669f99f78db0
mail.py: don't try to use TLS if python doesn't have SSL support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2964
diff
changeset
|
24 |
if not hasattr(socket, 'ssl'): |
669f99f78db0
mail.py: don't try to use TLS if python doesn't have SSL support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2964
diff
changeset
|
25 |
raise util.Abort(_("can't use TLS: Python SSL support " |
669f99f78db0
mail.py: don't try to use TLS if python doesn't have SSL support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2964
diff
changeset
|
26 |
"not installed")) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
27 |
ui.note(_('(using tls)\n')) |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
28 |
s.ehlo() |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
29 |
s.starttls() |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
30 |
s.ehlo() |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
31 |
username = ui.config('smtp', 'username') |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
32 |
password = ui.config('smtp', 'password') |
5749
4fba4fee0718
Patchbomb: Prompt password when using SMTP/TLS and no password in .hgrc.
Arun Thomas <arun.thomas@gmail.com>
parents:
5472
diff
changeset
|
33 |
if username and not password: |
4fba4fee0718
Patchbomb: Prompt password when using SMTP/TLS and no password in .hgrc.
Arun Thomas <arun.thomas@gmail.com>
parents:
5472
diff
changeset
|
34 |
password = ui.getpass() |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
35 |
if username and password: |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
36 |
ui.note(_('(authenticating to mail server as %s)\n') % |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
37 |
(username)) |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
38 |
s.login(username, password) |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
39 |
return s |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
40 |
|
5866
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
41 |
def _sendmail(ui, sender, recipients, msg): |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
42 |
'''send mail using sendmail.''' |
5866
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
43 |
program = ui.config('email', 'method') |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
44 |
cmdline = '%s -f %s %s' % (program, templater.email(sender), |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
45 |
' '.join(map(templater.email, recipients))) |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
46 |
ui.note(_('sending mail: %s\n') % cmdline) |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
47 |
fp = os.popen(cmdline, 'w') |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
48 |
fp.write(msg) |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
49 |
ret = fp.close() |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
50 |
if ret: |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
51 |
raise util.Abort('%s %s' % ( |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
52 |
os.path.basename(program.split(None, 1)[0]), |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
53 |
util.explain_exit(ret)[0])) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
54 |
|
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
55 |
def connect(ui): |
5866
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
56 |
'''make a mail connection. return a function to send mail. |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
57 |
call as sendmail(sender, list-of-recipients, msg).''' |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
58 |
|
5866
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
59 |
func = _sendmail |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
60 |
if ui.config('email', 'method', 'smtp') == 'smtp': |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
61 |
func = _smtp(ui) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
62 |
|
5866
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
63 |
def send(ui, sender, recipients, msg): |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
64 |
try: |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
65 |
return func.sendmail(sender, recipients, msg) |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
66 |
except smtplib.SMTPRecipientsRefused, inst: |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
67 |
recipients = [r[1] for r in inst.recipients.values()] |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
68 |
raise util.Abort('\n' + '\n'.join(recipients)) |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
69 |
except smtplib.SMTPException, inst: |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
70 |
raise util.Abort(inst) |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
71 |
|
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
72 |
return send |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
73 |
|
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
74 |
def sendmail(ui, sender, recipients, msg): |
5472
23889160905a
Catch smtp exceptions
Christian Ebert <blacktrash@gmx.net>
parents:
4489
diff
changeset
|
75 |
try: |
5866
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
76 |
send = connect(ui) |
dc6ed2736c81
patchbomb: prompt only once for SMTP password
Matt Mackall <mpm@selenic.com>
parents:
5749
diff
changeset
|
77 |
return send(sender, recipients, msg) |
5472
23889160905a
Catch smtp exceptions
Christian Ebert <blacktrash@gmx.net>
parents:
4489
diff
changeset
|
78 |
except smtplib.SMTPRecipientsRefused, inst: |
23889160905a
Catch smtp exceptions
Christian Ebert <blacktrash@gmx.net>
parents:
4489
diff
changeset
|
79 |
recipients = [r[1] for r in inst.recipients.values()] |
23889160905a
Catch smtp exceptions
Christian Ebert <blacktrash@gmx.net>
parents:
4489
diff
changeset
|
80 |
raise util.Abort('\n' + '\n'.join(recipients)) |
23889160905a
Catch smtp exceptions
Christian Ebert <blacktrash@gmx.net>
parents:
4489
diff
changeset
|
81 |
except smtplib.SMTPException, inst: |
23889160905a
Catch smtp exceptions
Christian Ebert <blacktrash@gmx.net>
parents:
4489
diff
changeset
|
82 |
raise util.Abort(inst) |
4489
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
83 |
|
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
84 |
def validateconfig(ui): |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
85 |
'''determine if we have enough config data to try sending email.''' |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
86 |
method = ui.config('email', 'method', 'smtp') |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
87 |
if method == 'smtp': |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
88 |
if not ui.config('smtp', 'host'): |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
89 |
raise util.Abort(_('smtp specified as email transport, ' |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
90 |
'but no smtp host configured')) |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
91 |
else: |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
92 |
if not util.find_exe(method): |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
93 |
raise util.Abort(_('%r specified as email transport, ' |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
94 |
'but not in PATH') % method) |