diff --git a/src/calibre/gui2/dialogs/config.py b/src/calibre/gui2/dialogs/config.py index 209212a6be..91bc988a22 100644 --- a/src/calibre/gui2/dialogs/config.py +++ b/src/calibre/gui2/dialogs/config.py @@ -1,6 +1,6 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' -import os, re, time, textwrap +import os, re, time, textwrap, sys, cStringIO from binascii import hexlify, unhexlify from PyQt4.Qt import QDialog, QMessageBox, QListWidgetItem, QIcon, \ @@ -11,6 +11,7 @@ from PyQt4.Qt import QDialog, QMessageBox, QListWidgetItem, QIcon, \ from calibre.constants import islinux, iswindows from calibre.gui2.dialogs.config_ui import Ui_Dialog +from calibre.gui2.dialogs.test_email_ui import Ui_Dialog as TE_Dialog from calibre.gui2 import qstring_to_unicode, choose_dir, error_dialog, config, \ ALL_COLUMNS, NONE, info_dialog, choose_files from calibre.utils.config import prefs @@ -134,6 +135,33 @@ class CategoryModel(QStringListModel): return self.icons[index.row()] return QStringListModel.data(self, index, role) +class TestEmail(QDialog, TE_Dialog): + + def __init__(self, accounts, parent): + QDialog.__init__(self, parent) + TE_Dialog.__init__(self) + self.setupUi(self) + opts = smtp_prefs().parse() + self.test_func = parent.test_email_settings + self.connect(self.test_button, SIGNAL('clicked(bool)'), self.test) + self.from_.setText(unicode(self.from_.text())%opts.from_) + if accounts: + self.to.setText(list(accounts.keys())[0]) + if opts.relay_host: + self.label.setText(_('Using: %s:%s@%s:%s and %s encryption')% + (opts.relay_username, unhexlify(opts.relay_password), + opts.relay_host, opts.relay_port, opts.encryption)) + + def test(self): + self.log.setPlainText(_('Sending...')) + self.test_button.setEnabled(False) + try: + tb = self.test_func(unicode(self.to.text())) + if not tb: + tb = _('Mail successfully sent') + self.log.setPlainText(tb) + finally: + self.test_button.setEnabled(True) class EmailAccounts(QAbstractTableModel): @@ -395,6 +423,8 @@ class ConfigDialog(QDialog, Ui_Dialog): self.connect(self.email_make_default, SIGNAL('clicked(bool)'), lambda c: self._email_accounts.make_default(self.email_view.currentIndex())) self.email_view.resizeColumnsToContents() + self.connect(self.test_email_button, SIGNAL('clicked(bool)'), + self.test_email) def add_email_account(self, checked): index = self._email_accounts.add() @@ -438,6 +468,33 @@ class ConfigDialog(QDialog, Ui_Dialog): conf.set('encryption', 'TLS' if self.relay_tls.isChecked() else 'SSL') return True + def test_email(self, *args): + if self.set_email_settings(): + TestEmail(self._email_accounts.accounts, self).exec_() + + def test_email_settings(self, to): + opts = smtp_prefs().parse() + from calibre.utils.smtp import sendmail, create_mail + buf = cStringIO.StringIO() + oout, oerr = sys.stdout, sys.stderr + sys.stdout = sys.stderr = buf + tb = None + try: + msg = create_mail(opts.from_, to, 'Test mail from calibre', + 'Test mail from calibre') + sendmail(msg, from_=opts.from_, to=[to], + verbose=3, timeout=30, relay=opts.relay_host, + username=opts.relay_username, + password=unhexlify(opts.relay_password), + encryption=opts.encryption, port=opts.relay_port) + except: + import traceback + tb = traceback.format_exc() + tb += '\n\nLog:\n' + buf.getvalue() + finally: + sys.stdout, sys.stderr = oout, oerr + return tb + def add_plugin(self): path = unicode(self.plugin_path.text()) if path and os.access(path, os.R_OK) and path.lower().endswith('.zip'): diff --git a/src/calibre/gui2/dialogs/config.ui b/src/calibre/gui2/dialogs/config.ui index 3f02ffc7f4..a75a6f0a8d 100644 --- a/src/calibre/gui2/dialogs/config.ui +++ b/src/calibre/gui2/dialogs/config.ui @@ -1,117 +1,118 @@ - + + Kovid Goyal Dialog - - + + 0 0 - 789 + 800 557 - + Configuration - - + + :/images/config.svg:/images/config.svg - - - + + + - - - + + + 1 0 - + 75 true - + true - + false - + 48 48 - + QAbstractItemView::ScrollPerItem - + QAbstractItemView::ScrollPerPixel - + QListView::TopToBottom - + 20 - + QListView::ListMode - - - + + + 100 0 - + 0 - - + + - + - - + + 16777215 70 - + &Location of ebooks (The ebooks are stored in folders sorted by author and metadata is stored in the file metadata.db) - + true - + location - + - + - - + + Browse for the new database location - + ... - - + + :/images/mimetypes/dir.svg:/images/mimetypes/dir.svg @@ -121,107 +122,107 @@ - - + + Show notification when &new version is available - - + + If you disable this setting, metadata is guessed from the filename instead. This can be configured in the Advanced section. - + Read &metadata from files - + true - - - - + + + + Format for &single file save: - + single_format - - + + - - - + + + Default network &timeout: - + timeout - - - + + + Set the default timeout for network fetches (i.e. anytime we go out to the internet to get information) - + seconds - + 2 - + 120 - + 5 - - + + - - - + + + Choose &language (requires restart): - + language - - + + - + Normal - + High - + Low - - - + + + Job &priority: - + priority @@ -229,19 +230,19 @@ - - + + Frequently used directories - - - + + + - - + + true - + 22 22 @@ -250,13 +251,13 @@ - + - + Qt::Vertical - + 20 40 @@ -265,25 +266,25 @@ - - + + Add a directory to the frequently used directories list - + ... - - + + :/images/plus.svg:/images/plus.svg - + Qt::Vertical - + 20 40 @@ -292,25 +293,25 @@ - - + + Remove a directory from the frequently used directories list - + ... - - + + :/images/list_remove.svg:/images/list_remove.svg - + Qt::Vertical - + 20 40 @@ -327,111 +328,111 @@ - - + + - - + + Use &Roman numerals for series number - + true - - + + Enable system &tray icon (needs restart) - - + + Show &notifications in system tray - - + + Show cover &browser in a separate window (needs restart) - - + + Automatically send downloaded &news to ebook reader - - + + &Delete news from library when it is sent to reader - + - - + + &Number of covers to show in browse mode (needs restart): - + cover_browse - + - - + + Toolbar - - - + + + - + Large - + Medium - + Small - - - + + + &Button size in toolbar - + toolbar_button_size - - - + + + Show &text in toolbar buttons - + true @@ -440,44 +441,44 @@ - + - - + + Select visible &columns in library view - + - + - - + + true - + QAbstractItemView::SelectRows - + - - + + ... - - + + :/images/arrow-up.svg:/images/arrow-up.svg - - + + Qt::Vertical - + 20 40 @@ -486,12 +487,12 @@ - - + + ... - - + + :/images/arrow-down.svg:/images/arrow-down.svg @@ -504,17 +505,17 @@ - - + + Use internal &viewer for: - - - - + + + + true - + QAbstractItemView::NoSelection @@ -535,99 +536,99 @@ - - - - - + + + + + calibre can send your books to you (or your reader) by email - + true - - + + - - + + Send email &from: - + email_from - - - <p>This is what will be present in the From: field of emails sent by calibre.<br> Set it to your email address + + + <p>This is what will be present in the From: field of emails sent by calibre.<br> Set it to your email address - - + + - - + + QAbstractItemView::SingleSelection - + QAbstractItemView::SelectRows - + - - + + Add an email address to which to send books - + &Add email - - + + :/images/plus.svg:/images/plus.svg - + 24 24 - + Qt::ToolButtonTextUnderIcon - - + + Make &default - - + + &Remove email - - + + :/images/minus.svg:/images/minus.svg - + 24 24 - + Qt::ToolButtonTextUnderIcon @@ -636,188 +637,208 @@ - - - - - - <p>A mail server is useful if the service you are sending mail to only accepts email from well know mail services. - - - Mail &Server - - - - - - calibre can <b>optionally</b> use a server to send mail + + + + <p>A mail server is useful if the service you are sending mail to only accepts email from well know mail services. + + + Mail &Server + + + + + + calibre can <b>optionally</b> use a server to send mail + + + true + + + + + + + &Hostname: + + + relay_host + + + + + + + The hostname of your mail server. For e.g. smtp.gmail.com + + + + + + + + + &Port: - - true + + relay_port - - - - &Hostname: + + + + The port your mail server listens for connections on. The default is 25 - - relay_host + + 1 - - - - - - The hostname of your mail server. For e.g. smtp.gmail.com + + 65555 - - - - - - - - &Port: - - - relay_port - - - - - - - The port your mail server listens for connections on. The default is 25 - - - 1 - - - 65555 - - - 25 - - - - - - - - - &Username: - - - relay_username - - - - - - - Your username on the mail server - - - - - - - &Password: - - - relay_password - - - - - - - Your password on the mail server - - - QLineEdit::Password - - - - - - - &Show - - - - - - - &Encryption: - - - relay_tls - - - - - - - Use TLS encryption when connecting to the mail server. This is the most common. - - - &TLS - - - true - - - - - - - Use SSL encryption when connecting to the mail server. - - - &SSL + + 25 - - + + + + + &Username: + + + relay_username + + + + + + + Your username on the mail server + + + + + + + &Password: + + + relay_password + + + + + + + Your password on the mail server + + + QLineEdit::Password + + + + + + + &Show + + + + + + + &Encryption: + + + relay_tls + + + + + + + Use TLS encryption when connecting to the mail server. This is the most common. + + + &TLS + + + true + + + + + + + Use SSL encryption when connecting to the mail server. + + + &SSL + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + - - + + Use Gmail - - + + :/images/gmail_logo.png:/images/gmail_logo.png - + 48 48 - + Qt::ToolButtonTextUnderIcon + + + + &Test email + + + - - + + - + - + Qt::Horizontal - + 40 20 @@ -826,21 +847,21 @@ - - + + Free unused diskspace from the database - + &Compact database - + Qt::Horizontal - + 40 20 @@ -851,17 +872,17 @@ - - + + &Metadata from file name - + - + Qt::Vertical - + 20 40 @@ -874,96 +895,96 @@ - - + + - - + + calibre contains a network server that allows you to access your book collection using a browser from anywhere in the world. Any changes to the settings will only take effect after a server restart. - + true - - - - + + + + Server &port: - + port - - - + + + 1025 - + 16000 - + 8080 - - - + + + &Username: - + username - - + + - - - + + + &Password: - + password - - - + + + If you leave the password blank, anyone will be able to access your book collection using the web interface. - - - + + + &Show password - - - + + + The maximum size (widthxheight) for displayed covers. Larger covers are resized. - + - - - + + + Max. &cover size: - + max_cover_size @@ -971,27 +992,27 @@ - + - - + + &Start Server - - + + St&op Server - - + + Qt::Horizontal - + 40 20 @@ -1000,8 +1021,8 @@ - - + + &Test Server @@ -1009,25 +1030,25 @@ - - + + Run server &automatically on startup - - + + View &server logs - - + + Qt::Vertical - + 20 40 @@ -1036,21 +1057,21 @@ - - + + If you want to use the content server to access your ebook collection on your iphone with Stanza, you will need to add the URL http://myhostname:8080/stanza as a new catalog in the stanza reader on your iphone. Here myhostname should be the fully qualified hostname or the IP address of this computer. - + true - - + + Qt::Vertical - + 20 40 @@ -1060,53 +1081,53 @@ - - + + - - + + Here you can customize the behavior of Calibre by controlling what plugins it uses. - + true - - + + 32 32 - + true - + true - + - - + + Enable/&Disable plugin - - + + &Customize plugin - - + + &Remove plugin @@ -1114,33 +1135,33 @@ - - + + Add new plugin - + - + - - + + Plugin &file: - + plugin_path - + - - + + ... - - + + :/images/document_open.svg:/images/document_open.svg @@ -1148,13 +1169,13 @@ - + - - + + Qt::Horizontal - + 40 20 @@ -1163,8 +1184,8 @@ - - + + &Add @@ -1180,12 +1201,12 @@ - - - + + + Qt::Horizontal - + QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -1193,7 +1214,7 @@ - + @@ -1202,11 +1223,11 @@ Dialog accept() - + 239 558 - + 157 274 @@ -1218,11 +1239,11 @@ Dialog reject() - + 307 558 - + 286 274 diff --git a/src/calibre/gui2/dialogs/test_email.ui b/src/calibre/gui2/dialogs/test_email.ui new file mode 100644 index 0000000000..f1d5568c03 --- /dev/null +++ b/src/calibre/gui2/dialogs/test_email.ui @@ -0,0 +1,103 @@ + + + Dialog + + + + 0 + 0 + 542 + 418 + + + + Test email settings + + + + :/images/config.svg:/images/config.svg + + + + + + Send test mail from %s to: + + + true + + + + + + + + + + + + + true + + + + + + + &Test + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/calibre/utils/smtp.py b/src/calibre/utils/smtp.py index 79e46c03c3..0234e27c55 100644 --- a/src/calibre/utils/smtp.py +++ b/src/calibre/utils/smtp.py @@ -45,15 +45,17 @@ def create_mail(from_, to, subject, text=None, attachment_data=None, return outer.as_string() -def get_mx(host): +def get_mx(host, verbose=0): import dns.resolver + if verbose: + print 'Find mail exchanger for', host answers = list(dns.resolver.query(host, 'MX')) answers.sort(cmp=lambda x, y: cmp(int(x.preference), int(y.preference))) return [str(x.exchange) for x in answers] def sendmail_direct(from_, to, msg, timeout, localhost, verbose): import smtplib - hosts = get_mx(to.split('@')[-1].strip()) + hosts = get_mx(to.split('@')[-1].strip(), verbose) timeout=None # Non blocking sockets sometimes don't work s = smtplib.SMTP(timeout=timeout, local_hostname=localhost) s.set_debuglevel(verbose)