summaryrefslogtreecommitdiff
path: root/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/mail.py
diff options
context:
space:
mode:
Diffstat (limited to 'eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/mail.py')
-rw-r--r--eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/mail.py226
1 files changed, 0 insertions, 226 deletions
diff --git a/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/mail.py b/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/mail.py
deleted file mode 100644
index 3aa1a55..0000000
--- a/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/mail.py
+++ /dev/null
@@ -1,226 +0,0 @@
-# mail.py - mail sending bits for mercurial
-#
-# Copyright 2006 Matt Mackall <mpm@selenic.com>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2 or any later version.
-
-from i18n import _
-import util, encoding
-import os, smtplib, socket, quopri
-import email.Header, email.MIMEText, email.Utils
-
-_oldheaderinit = email.Header.Header.__init__
-def _unifiedheaderinit(self, *args, **kw):
- """
- Python2.7 introduces a backwards incompatible change
- (Python issue1974, r70772) in email.Generator.Generator code:
- pre-2.7 code passed "continuation_ws='\t'" to the Header
- constructor, and 2.7 removed this parameter.
-
- Default argument is continuation_ws=' ', which means that the
- behaviour is different in <2.7 and 2.7
-
- We consider the 2.7 behaviour to be preferable, but need
- to have an unified behaviour for versions 2.4 to 2.7
- """
- # override continuation_ws
- kw['continuation_ws'] = ' '
- _oldheaderinit(self, *args, **kw)
-
-email.Header.Header.__dict__['__init__'] = _unifiedheaderinit
-
-def _smtp(ui):
- '''build an smtp connection and return a function to send mail'''
- local_hostname = ui.config('smtp', 'local_hostname')
- s = smtplib.SMTP(local_hostname=local_hostname)
- mailhost = ui.config('smtp', 'host')
- if not mailhost:
- raise util.Abort(_('smtp.host not configured - cannot send mail'))
- mailport = util.getport(ui.config('smtp', 'port', 25))
- ui.note(_('sending mail: smtp host %s, port %s\n') %
- (mailhost, mailport))
- s.connect(host=mailhost, port=mailport)
- if ui.configbool('smtp', 'tls'):
- if not hasattr(socket, 'ssl'):
- raise util.Abort(_("can't use TLS: Python SSL support "
- "not installed"))
- ui.note(_('(using tls)\n'))
- s.ehlo()
- s.starttls()
- s.ehlo()
- username = ui.config('smtp', 'username')
- password = ui.config('smtp', 'password')
- if username and not password:
- password = ui.getpass()
- if username and password:
- ui.note(_('(authenticating to mail server as %s)\n') %
- (username))
- try:
- s.login(username, password)
- except smtplib.SMTPException, inst:
- raise util.Abort(inst)
-
- def send(sender, recipients, msg):
- try:
- return s.sendmail(sender, recipients, msg)
- except smtplib.SMTPRecipientsRefused, inst:
- recipients = [r[1] for r in inst.recipients.values()]
- raise util.Abort('\n' + '\n'.join(recipients))
- except smtplib.SMTPException, inst:
- raise util.Abort(inst)
-
- return send
-
-def _sendmail(ui, sender, recipients, msg):
- '''send mail using sendmail.'''
- program = ui.config('email', 'method')
- cmdline = '%s -f %s %s' % (program, util.email(sender),
- ' '.join(map(util.email, recipients)))
- ui.note(_('sending mail: %s\n') % cmdline)
- fp = util.popen(cmdline, 'w')
- fp.write(msg)
- ret = fp.close()
- if ret:
- raise util.Abort('%s %s' % (
- os.path.basename(program.split(None, 1)[0]),
- util.explain_exit(ret)[0]))
-
-def connect(ui):
- '''make a mail connection. return a function to send mail.
- call as sendmail(sender, list-of-recipients, msg).'''
- if ui.config('email', 'method', 'smtp') == 'smtp':
- return _smtp(ui)
- return lambda s, r, m: _sendmail(ui, s, r, m)
-
-def sendmail(ui, sender, recipients, msg):
- send = connect(ui)
- return send(sender, recipients, msg)
-
-def validateconfig(ui):
- '''determine if we have enough config data to try sending email.'''
- method = ui.config('email', 'method', 'smtp')
- if method == 'smtp':
- if not ui.config('smtp', 'host'):
- raise util.Abort(_('smtp specified as email transport, '
- 'but no smtp host configured'))
- else:
- if not util.find_exe(method):
- raise util.Abort(_('%r specified as email transport, '
- 'but not in PATH') % method)
-
-def mimetextpatch(s, subtype='plain', display=False):
- '''If patch in utf-8 transfer-encode it.'''
-
- enc = None
- for line in s.splitlines():
- if len(line) > 950:
- s = quopri.encodestring(s)
- enc = "quoted-printable"
- break
-
- cs = 'us-ascii'
- if not display:
- try:
- s.decode('us-ascii')
- except UnicodeDecodeError:
- try:
- s.decode('utf-8')
- cs = 'utf-8'
- except UnicodeDecodeError:
- # We'll go with us-ascii as a fallback.
- pass
-
- msg = email.MIMEText.MIMEText(s, subtype, cs)
- if enc:
- del msg['Content-Transfer-Encoding']
- msg['Content-Transfer-Encoding'] = enc
- return msg
-
-def _charsets(ui):
- '''Obtains charsets to send mail parts not containing patches.'''
- charsets = [cs.lower() for cs in ui.configlist('email', 'charsets')]
- fallbacks = [encoding.fallbackencoding.lower(),
- encoding.encoding.lower(), 'utf-8']
- for cs in fallbacks: # find unique charsets while keeping order
- if cs not in charsets:
- charsets.append(cs)
- return [cs for cs in charsets if not cs.endswith('ascii')]
-
-def _encode(ui, s, charsets):
- '''Returns (converted) string, charset tuple.
- Finds out best charset by cycling through sendcharsets in descending
- order. Tries both encoding and fallbackencoding for input. Only as
- last resort send as is in fake ascii.
- Caveat: Do not use for mail parts containing patches!'''
- try:
- s.decode('ascii')
- except UnicodeDecodeError:
- sendcharsets = charsets or _charsets(ui)
- for ics in (encoding.encoding, encoding.fallbackencoding):
- try:
- u = s.decode(ics)
- except UnicodeDecodeError:
- continue
- for ocs in sendcharsets:
- try:
- return u.encode(ocs), ocs
- except UnicodeEncodeError:
- pass
- except LookupError:
- ui.warn(_('ignoring invalid sendcharset: %s\n') % ocs)
- # if ascii, or all conversion attempts fail, send (broken) ascii
- return s, 'us-ascii'
-
-def headencode(ui, s, charsets=None, display=False):
- '''Returns RFC-2047 compliant header from given string.'''
- if not display:
- # split into words?
- s, cs = _encode(ui, s, charsets)
- return str(email.Header.Header(s, cs))
- return s
-
-def _addressencode(ui, name, addr, charsets=None):
- name = headencode(ui, name, charsets)
- try:
- acc, dom = addr.split('@')
- acc = acc.encode('ascii')
- dom = dom.decode(encoding.encoding).encode('idna')
- addr = '%s@%s' % (acc, dom)
- except UnicodeDecodeError:
- raise util.Abort(_('invalid email address: %s') % addr)
- except ValueError:
- try:
- # too strict?
- addr = addr.encode('ascii')
- except UnicodeDecodeError:
- raise util.Abort(_('invalid local address: %s') % addr)
- return email.Utils.formataddr((name, addr))
-
-def addressencode(ui, address, charsets=None, display=False):
- '''Turns address into RFC-2047 compliant header.'''
- if display or not address:
- return address or ''
- name, addr = email.Utils.parseaddr(address)
- return _addressencode(ui, name, addr, charsets)
-
-def addrlistencode(ui, addrs, charsets=None, display=False):
- '''Turns a list of addresses into a list of RFC-2047 compliant headers.
- A single element of input list may contain multiple addresses, but output
- always has one address per item'''
- if display:
- return [a.strip() for a in addrs if a.strip()]
-
- result = []
- for name, addr in email.Utils.getaddresses(addrs):
- if name or addr:
- result.append(_addressencode(ui, name, addr, charsets))
- return result
-
-def mimeencode(ui, s, charsets=None, display=False):
- '''creates mime text object, encodes it if needed, and sets
- charset and transfer-encoding accordingly.'''
- cs = 'us-ascii'
- if not display:
- s, cs = _encode(ui, s, charsets)
- return email.MIMEText.MIMEText(s, 'plain', cs)