Fix sending by email not working on computers with non-ascii hostnames. Fixes #1256549 [E-mailing has problems on French Windows installation](https://bugs.launchpad.net/calibre/+bug/1256549)

This commit is contained in:
Kovid Goyal 2013-12-01 09:43:58 +05:30
parent 4accf0954c
commit 2f194b2776

View File

@ -9,8 +9,9 @@ This module implements a simple commandline SMTP client that supports:
* Background delivery with failures being saved in a maildir mailbox * Background delivery with failures being saved in a maildir mailbox
''' '''
import sys, traceback, os import sys, traceback, os, socket
from calibre import isbytestring from calibre import isbytestring
from calibre.utils.filenames import ascii_text
def create_mail(from_, to, subject, text=None, attachment_data=None, def create_mail(from_, to, subject, text=None, attachment_data=None,
attachment_type=None, attachment_name=None): attachment_type=None, attachment_name=None):
@ -61,12 +62,34 @@ def get_mx(host, verbose=0):
int(getattr(y, 'preference', sys.maxint)))) int(getattr(y, 'preference', sys.maxint))))
return [str(x.exchange) for x in answers if hasattr(x, 'exchange')] return [str(x.exchange) for x in answers if hasattr(x, 'exchange')]
def safe_localhost():
# RFC 2821 says we should use the fqdn in the EHLO/HELO verb, and
# if that can't be calculated, that we should use a domain literal
# instead (essentially an encoded IP address like [A.B.C.D]).
fqdn = socket.getfqdn()
if '.' in fqdn:
# Some mail servers have problems with non-ascii local hostnames, see
# https://bugs.launchpad.net/bugs/1256549
try:
local_hostname = ascii_text(fqdn)
except:
local_hostname = 'localhost.localdomain'
else:
# We can't find an fqdn hostname, so use a domain literal
addr = '127.0.0.1'
try:
addr = socket.gethostbyname(socket.gethostname())
except socket.gaierror:
pass
local_hostname = '[%s]' % addr
return local_hostname
def sendmail_direct(from_, to, msg, timeout, localhost, verbose, def sendmail_direct(from_, to, msg, timeout, localhost, verbose,
debug_output=None): debug_output=None):
import calibre.utils.smtplib as smtplib import calibre.utils.smtplib as smtplib
hosts = get_mx(to.split('@')[-1].strip(), verbose) hosts = get_mx(to.split('@')[-1].strip(), verbose)
timeout=None # Non blocking sockets sometimes don't work timeout=None # Non blocking sockets sometimes don't work
kwargs = dict(timeout=timeout, local_hostname=localhost) kwargs = dict(timeout=timeout, local_hostname=localhost or safe_localhost())
if debug_output is not None: if debug_output is not None:
kwargs['debug_to'] = debug_output kwargs['debug_to'] = debug_output
s = smtplib.SMTP(**kwargs) s = smtplib.SMTP(**kwargs)
@ -96,7 +119,7 @@ def sendmail(msg, from_, to, localhost=None, verbose=0, timeout=None,
cls = smtplib.SMTP_SSL if encryption == 'SSL' else smtplib.SMTP cls = smtplib.SMTP_SSL if encryption == 'SSL' else smtplib.SMTP
timeout = None # Non-blocking sockets sometimes don't work timeout = None # Non-blocking sockets sometimes don't work
port = int(port) port = int(port)
kwargs = dict(timeout=timeout, local_hostname=localhost) kwargs = dict(timeout=timeout, local_hostname=localhost or safe_localhost())
if debug_output is not None: if debug_output is not None:
kwargs['debug_to'] = debug_output kwargs['debug_to'] = debug_output
s = cls(**kwargs) s = cls(**kwargs)
@ -203,7 +226,6 @@ def main(args=sys.argv):
parser = option_parser() parser = option_parser()
opts, args = parser.parse_args(args) opts, args = parser.parse_args(args)
if len(args) > 1: if len(args) > 1:
if len(args) < 4: if len(args) < 4:
print ('You must specify the from address, to address and body text' print ('You must specify the from address, to address and body text'