def add_recipient(self): to = unicode(self.address.text()).strip() if not to: return error_dialog( self, _('Need address'), _('You must specify an address'), show=True) formats = ','.join([x.strip().upper() for x in unicode(self.formats.text()).strip().split(',') if x.strip()]) if not formats: return error_dialog( self, _('Need formats'), _('You must specify at least one format to send'), show=True) opts = email_config().parse() if to in opts.accounts: return error_dialog( self, _('Already exists'), _('The recipient %s already exists') % to, show=True) acc = opts.accounts acc[to] = [formats, False, False] c = email_config() c.set('accounts', acc) alias = unicode(self.alias.text()).strip() if alias: opts.aliases[to] = alias c.set('aliases', opts.aliases) subject = unicode(self.subject.text()).strip() if subject: opts.subjects[to] = subject c.set('subjects', opts.subjects) self.create_item(alias or to, to, checked=True)
def email_news(mi, remove, get_fmts, done, job_manager): opts = email_config().parse() accounts = [(account, [x.strip().lower() for x in x[0].split(',')]) for account, x in opts.accounts.items() if x[1]] sent_mails = [] for i, x in enumerate(accounts): account, fmts = x files = get_fmts(fmts) files = [f for f in files if f is not None] if not files: continue attachment = files[0] to_s = [account] subjects = [_('News:')+' '+mi.title] texts = [ _('Attached is the %s periodical downloaded by calibre.') % (mi.title,) ] attachment_names = [ascii_filename(mi.title)+os.path.splitext(attachment)[1]] attachments = [attachment] jobnames = [mi.title] do_remove = [] if i == len(accounts) - 1: do_remove = remove send_mails(jobnames, Dispatcher(partial(done, remove=do_remove)), attachments, to_s, subjects, texts, attachment_names, job_manager) sent_mails.append(to_s[0]) return sent_mails
def sendmail(self, attachment, aname, to, subject, text, log): logged = False while time.time() - self.last_send_time <= self.rate_limit: if not logged and self.rate_limit > 0: log('Waiting %s seconds before sending, to avoid being marked as spam.\nYou can control this delay via Preferences->Tweaks' % self.rate_limit) logged = True time.sleep(1) try: opts = email_config().parse() from_ = opts.from_ if not from_: from_ = 'calibre <calibre@' + socket.getfqdn() + '>' with lopen(attachment, 'rb') as f: msg = compose_mail(from_, to, text, subject, f, aname) efrom = extract_email_address(from_) eto = [] for x in to.split(','): eto.append(extract_email_address(x.strip())) sendmail(msg, efrom, eto, localhost=None, verbose=1, relay=opts.relay_host, username=opts.relay_username, password=unhexlify(opts.relay_password).decode('utf-8'), port=opts.relay_port, encryption=opts.encryption, debug_output=log.debug) finally: self.last_send_time = time.time()
def calculate_rate_limit(self): self.rate_limit = 1 opts = email_config().parse() rh = opts.relay_host if rh and ( 'gmail.com' in rh or 'live.com' in rh): self.rate_limit = tweaks['public_smtp_relay_delay']
def build_email_entries(self, sync_menu): from calibre.gui2.device import DeviceAction for ac in self.email_actions: self.removeAction(ac) self.email_actions = [] self.memory = [] opts = email_config().parse() if opts.accounts: self.email_to_menu = QMenu(_('Email to') + '...', self) ac = self.addMenu(self.email_to_menu) self.email_actions.append(ac) self.email_to_and_delete_menu = QMenu( _('Email to and delete from library') + '...', self) keys = sorted(opts.accounts.keys()) def sk(account): return primary_sort_key(opts.aliases.get(account) or account) for account in sorted(keys, key=sk): formats, auto, default = opts.accounts[account] subject = opts.subjects.get(account, '') alias = opts.aliases.get(account, '') dest = 'mail:' + account + ';' + formats + ';' + subject action1 = DeviceAction(dest, False, False, I('mail.png'), alias or account) action2 = DeviceAction(dest, True, False, I('mail.png'), (alias or account) + ' ' + _('(delete from library)')) self.email_to_menu.addAction(action1) self.email_to_and_delete_menu.addAction(action2) tuple(map(self.memory.append, (action1, action2))) if default: ac = DeviceAction(dest, False, False, I('mail.png'), _('Email to') + ' ' + (alias or account)) self.addAction(ac) self.email_actions.append(ac) ac.a_s.connect(sync_menu.action_triggered) action1.a_s.connect(sync_menu.action_triggered) action2.a_s.connect(sync_menu.action_triggered) action1 = DeviceAction('choosemail:', False, False, I('mail.png'), _('Select recipients')) action2 = DeviceAction( 'choosemail:', True, False, I('mail.png'), _('Select recipients') + ' ' + _('(delete from library)')) self.email_to_menu.addAction(action1) self.email_to_and_delete_menu.addAction(action2) tuple(map(self.memory.append, (action1, action2))) tac1 = DeviceAction('choosemail:', False, False, I('mail.png'), _('Email to selected recipients...')) self.addAction(tac1) tac1.a_s.connect(sync_menu.action_triggered) self.memory.append(tac1), self.email_actions.append(tac1) ac = self.addMenu(self.email_to_and_delete_menu) self.email_actions.append(ac) action1.a_s.connect(sync_menu.action_triggered) action2.a_s.connect(sync_menu.action_triggered) else: ac = self.addAction(_('Setup email based sharing of books')) self.email_actions.append(ac) ac.triggered.connect(self.setup_email)
def sendmail(self, attachment, aname, to, subject, text, log): logged = False while time.time() - self.last_send_time <= self.rate_limit: if not logged and self.rate_limit > 0: log('Waiting %s seconds before sending, to avoid being marked as spam.\nYou can control this delay via Preferences->Tweaks' % self.rate_limit) logged = True time.sleep(1) try: opts = email_config().parse() from_ = opts.from_ if not from_: from_ = 'calibre <calibre@'+socket.getfqdn()+'>' with lopen(attachment, 'rb') as f: msg = compose_mail(from_, to, text, subject, f, aname) efrom = extract_email_address(from_) eto = [] for x in to.split(','): eto.append(extract_email_address(x.strip())) sendmail(msg, efrom, eto, localhost=None, verbose=1, relay=opts.relay_host, username=opts.relay_username, password=unhexlify(opts.relay_password).decode('utf-8'), port=opts.relay_port, encryption=opts.encryption, debug_output=log.debug) finally: self.last_send_time = time.time()
def email_news(mi, remove, get_fmts, done, job_manager): opts = email_config().parse() accounts = [(account, [x.strip().lower() for x in x[0].split(',')]) for account, x in opts.accounts.items() if x[1]] sent_mails = [] for i, x in enumerate(accounts): account, fmts = x files = get_fmts(fmts) files = [f for f in files if f is not None] if not files: continue attachment = files[0] to_s = [account] subjects = [_('News:') + ' ' + mi.title] texts = [ _('Attached is the %s periodical downloaded by calibre.') % (mi.title, ) ] attachment_names = [ ascii_filename(mi.title) + os.path.splitext(attachment)[1] ] attachments = [attachment] jobnames = [mi.title] do_remove = [] if i == len(accounts) - 1: do_remove = remove send_mails(jobnames, Dispatcher(partial(done, remove=do_remove)), attachments, to_s, subjects, texts, attachment_names, job_manager) sent_mails.append(to_s[0]) return sent_mails
def sendmail(self, attachment, aname, to, subject, text, log): while time.time() - self.last_send_time <= self.rate_limit: time.sleep(1) try: opts = email_config().parse() from_ = opts.from_ if not from_: from_ = 'calibre <calibre@' + socket.getfqdn() + '>' with lopen(attachment, 'rb') as f: msg = compose_mail(from_, to, text, subject, f, aname) efrom, eto = map(extract_email_address, (from_, to)) eto = [eto] sendmail(msg, efrom, eto, localhost=None, verbose=1, relay=opts.relay_host, username=opts.relay_username, password=unhexlify(opts.relay_password), port=opts.relay_port, encryption=opts.encryption, debug_output=log.debug) finally: self.last_send_time = time.time()
def build_email_entries(self, sync_menu): from calibre.gui2.device import DeviceAction for ac in self.email_actions: self.removeAction(ac) self.email_actions = [] self.memory = [] opts = email_config().parse() if opts.accounts: self.email_to_menu = QMenu(_('Email to')+'...', self) ac = self.addMenu(self.email_to_menu) self.email_actions.append(ac) self.email_to_and_delete_menu = QMenu( _('Email to and delete from library')+'...', self) keys = sorted(opts.accounts.keys()) def sk(account): return primary_sort_key(opts.aliases.get(account) or account) for account in sorted(keys, key=sk): formats, auto, default = opts.accounts[account] subject = opts.subjects.get(account, '') alias = opts.aliases.get(account, '') dest = 'mail:'+account+';'+formats+';'+subject action1 = DeviceAction(dest, False, False, I('mail.png'), alias or account) action2 = DeviceAction(dest, True, False, I('mail.png'), (alias or account) + ' ' + _('(delete from library)')) self.email_to_menu.addAction(action1) self.email_to_and_delete_menu.addAction(action2) map(self.memory.append, (action1, action2)) if default: ac = DeviceAction(dest, False, False, I('mail.png'), _('Email to') + ' ' +(alias or account)) self.addAction(ac) self.email_actions.append(ac) ac.a_s.connect(sync_menu.action_triggered) action1.a_s.connect(sync_menu.action_triggered) action2.a_s.connect(sync_menu.action_triggered) action1 = DeviceAction('choosemail:', False, False, I('mail.png'), _('Select recipients')) action2 = DeviceAction('choosemail:', True, False, I('mail.png'), _('Select recipients') + ' ' + _('(delete from library)')) self.email_to_menu.addAction(action1) self.email_to_and_delete_menu.addAction(action2) map(self.memory.append, (action1, action2)) tac1 = DeviceAction('choosemail:', False, False, I('mail.png'), _('Email to selected recipients...')) self.addAction(tac1) tac1.a_s.connect(sync_menu.action_triggered) self.memory.append(tac1), self.email_actions.append(tac1) ac = self.addMenu(self.email_to_and_delete_menu) self.email_actions.append(ac) action1.a_s.connect(sync_menu.action_triggered) action2.a_s.connect(sync_menu.action_triggered) else: ac = self.addAction(_('Setup email based sharing of books')) self.email_actions.append(ac) ac.triggered.connect(self.setup_email)
def calculate_rate_limit(self): self.rate_limit = 1 opts = email_config().parse() rh = opts.relay_host if rh: for suffix in tweaks['public_smtp_relay_host_suffixes']: if rh.lower().endswith(suffix): self.rate_limit = tweaks['public_smtp_relay_delay'] break
def init_list(self): opts = email_config().parse() self.items = [] def sk(account): return primary_sort_key(opts.aliases.get(account) or account) for key in sorted(opts.accounts or (), key=sk): self.create_item(opts.aliases.get(key, key), key)
def ans(self): opts = email_config().parse() ans = [] for i in self.items: if i.checkState() == Qt.Checked: to = unicode(i.data(Qt.UserRole).toString()) fmts = tuple(x.strip().upper() for x in (opts.accounts[to][0] or '').split(',')) subject = opts.subjects.get(to, '') ans.append((to, fmts, subject)) return ans
def build_email_entries(self, sync_menu): from calibre.gui2.device import DeviceAction for ac in self.email_actions: self.removeAction(ac) self.email_actions = [] self.memory = [] opts = email_config().parse() if opts.accounts: self.email_to_menu = QMenu(_("Email to") + "...", self) ac = self.addMenu(self.email_to_menu) self.email_actions.append(ac) self.email_to_and_delete_menu = QMenu(_("Email to and delete from library") + "...", self) keys = sorted(opts.accounts.keys()) for account in keys: formats, auto, default = opts.accounts[account] subject = opts.subjects.get(account, "") alias = opts.aliases.get(account, "") dest = "mail:" + account + ";" + formats + ";" + subject action1 = DeviceAction(dest, False, False, I("mail.png"), alias or account) action2 = DeviceAction( dest, True, False, I("mail.png"), (alias or account) + " " + _("(delete from library)") ) self.email_to_menu.addAction(action1) self.email_to_and_delete_menu.addAction(action2) map(self.memory.append, (action1, action2)) if default: ac = DeviceAction(dest, False, False, I("mail.png"), _("Email to") + " " + (alias or account)) self.addAction(ac) self.email_actions.append(ac) ac.a_s.connect(sync_menu.action_triggered) action1.a_s.connect(sync_menu.action_triggered) action2.a_s.connect(sync_menu.action_triggered) action1 = DeviceAction("choosemail:", False, False, I("mail.png"), _("Select recipients")) action2 = DeviceAction( "choosemail:", True, False, I("mail.png"), _("Select recipients") + " " + _("(delete from library)") ) self.email_to_menu.addAction(action1) self.email_to_and_delete_menu.addAction(action2) map(self.memory.append, (action1, action2)) tac1 = DeviceAction("choosemail:", False, False, I("mail.png"), _("Email to selected recipients...")) self.addAction(tac1) tac1.a_s.connect(sync_menu.action_triggered) self.memory.append(tac1) ac = self.addMenu(self.email_to_and_delete_menu) self.email_actions.append(ac) action1.a_s.connect(sync_menu.action_triggered) action2.a_s.connect(sync_menu.action_triggered) else: ac = self.addAction(_("Setup email based sharing of books")) self.email_actions.append(ac) ac.triggered.connect(self.setup_email)
def sendmail(self, attachment, aname, to, subject, text, log): logged = False while time.time() - self.last_send_time <= self.rate_limit: if not logged and self.rate_limit > 0: log('Waiting %s seconds before sending, to avoid being marked as spam.\nYou can control this delay via Preferences->Tweaks' % self.rate_limit) logged = True time.sleep(1) try: opts = email_config().parse() from_ = opts.from_ if not from_: from_ = 'calibre <calibre@' + socket.getfqdn() + '>' with lopen(attachment, 'rb') as f: msg = compose_mail(from_, to, text, subject, f, aname) efrom = extract_email_address(from_) eto = [] for x in to.split(','): eto.append(extract_email_address(x.strip())) def safe_debug(*args, **kwargs): try: return log.debug(*args, **kwargs) except Exception: pass relay = opts.relay_host if relay and relay == 'smtp.live.com': # Microsoft changed the SMTP server relay = 'smtp-mail.outlook.com' sendmail(msg, efrom, eto, localhost=None, verbose=1, relay=relay, username=opts.relay_username, password=from_hex_unicode(opts.relay_password), port=opts.relay_port, encryption=opts.encryption, debug_output=safe_debug) finally: self.last_send_time = time.time()
def email_news(self, id_): opts = email_config().parse() if opts.relay_prompt: return mi = self.library_view.model().db.get_metadata(id_, index_is_id=True) remove = [id_] if config['delete_news_from_library_on_upload'] \ else [] def get_fmts(fmts): files, auto = self.library_view.model().\ get_preferred_formats_from_ids([id_], fmts, set_metadata=True, use_plugboard=plugboard_email_value, plugboard_formats=plugboard_email_formats) return files sent_mails = email_news(mi, remove, get_fmts, self.email_sent, self.job_manager, self.smtp_password) if sent_mails: self.status_bar.show_message( _('Sent news to') + ' ' + ', '.join(sent_mails), 3000)
def sendmail(self, attachment, aname, to, subject, text, log): while time.time() - self.last_send_time <= self.rate_limit: time.sleep(1) try: opts = email_config().parse() from_ = opts.from_ if not from_: from_ = 'calibre <calibre@'+socket.getfqdn()+'>' with lopen(attachment, 'rb') as f: msg = compose_mail(from_, to, text, subject, f, aname) efrom, eto = map(extract_email_address, (from_, to)) eto = [eto] sendmail(msg, efrom, eto, localhost=None, verbose=1, relay=opts.relay_host, username=opts.relay_username, password=unhexlify(opts.relay_password), port=opts.relay_port, encryption=opts.encryption, debug_output=log.debug) finally: self.last_send_time = time.time()
def init_list(self): opts = email_config().parse() self.items = [] for key in sorted(opts.accounts or (), key=sort_key): self.create_item(opts.aliases.get(key, key), key)