commit 126454c0e657a909ab4568f92b4ae059ec773f92
parent b9d270d438a826c944840bf34c5435be4260e09d
Author: ThomasV <thomasv@gitorious>
Date: Tue, 11 Nov 2014 11:08:25 +0100
email plugin
Diffstat:
2 files changed, 222 insertions(+), 0 deletions(-)
diff --git a/plugins/__init__.py b/plugins/__init__.py
@@ -48,6 +48,12 @@ descriptions = [
'available_for': ['qt'],
},
{
+ 'name': 'email',
+ 'fullname': 'Email',
+ 'description': _("Send and receive payment request with an email account"),
+ 'available_for': ['qt'],
+ },
+ {
'name': 'exchange_rate',
'fullname': _("Exchange rates"),
'description': _("Exchange rates and currency conversion tools."),
diff --git a/plugins/email.py b/plugins/email.py
@@ -0,0 +1,216 @@
+#!/usr/bin/env python
+#
+# Electrum - Lightweight Bitcoin Client
+# Copyright (C) 2015 Thomas Voegtlin
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import
+
+import socket
+import time
+import threading
+import base64
+import re
+import platform
+from decimal import Decimal
+from Queue import Queue
+
+import smtplib
+import imaplib
+import email
+from email.MIMEMultipart import MIMEMultipart
+from email.MIMEBase import MIMEBase
+from email import Encoders
+
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+import PyQt4.QtCore as QtCore
+import PyQt4.QtGui as QtGui
+
+from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED
+from electrum.plugins import BasePlugin, hook
+from electrum import util
+from electrum.paymentrequest import PaymentRequest
+from electrum.i18n import _
+from electrum_gui.qt.util import text_dialog, EnterButton
+
+
+
+class Processor(threading.Thread):
+ polling_interval = 5*60
+
+ def __init__(self, imap_server, username, password, callback):
+ threading.Thread.__init__(self)
+ self.daemon = True
+ self.username = username
+ self.password = password
+ self.imap_server = imap_server
+ self.on_receive = callback
+
+ def poll(self):
+ try:
+ self.M.select()
+ except:
+ return
+ typ, data = self.M.search(None, 'ALL')
+ for num in data[0].split():
+ typ, msg_data = self.M.fetch(num, '(RFC822)')
+ msg = email.message_from_string(msg_data[0][1])
+ p = msg.get_payload()
+ if not msg.is_multipart():
+ p = [p]
+ continue
+ for item in p:
+ if item.get_content_type() == "application/bitcoin-paymentrequest":
+ pr_str = item.get_payload()
+ pr_str = base64.b64decode(pr_str)
+ self.on_receive(pr_str)
+
+ def run(self):
+ self.M = imaplib.IMAP4_SSL(self.imap_server)
+ self.M.login(self.username, self.password)
+ while True:
+ self.poll()
+ time.sleep(self.polling_interval)
+ self.M.close()
+ self.M.logout()
+
+ def send(self, recipient, message, payment_request):
+ msg = MIMEMultipart()
+ msg['Subject'] = message
+ msg['To'] = recipient
+ msg['From'] = self.username
+ part = MIMEBase('application', "bitcoin-paymentrequest")
+ part.set_payload(payment_request)
+ Encoders.encode_base64(part)
+ part.add_header('Content-Disposition', 'attachment; filename="payreq.btc"')
+ msg.attach(part)
+ s = smtplib.SMTP_SSL(self.imap_server, timeout=2)
+ s.login(self.username, self.password)
+ s.sendmail(self.username, [recipient], msg.as_string())
+ s.quit()
+
+
+class Plugin(BasePlugin):
+
+ def fullname(self):
+ return 'Email'
+
+ def description(self):
+ return _("Send and receive payment requests via email")
+
+ def is_available(self):
+ return True
+
+ def __init__(self, a, b):
+ BasePlugin.__init__(self, a, b)
+ self.imap_server = self.config.get('email_server', '')
+ self.username = self.config.get('email_username', '')
+ self.password = self.config.get('email_password', '')
+ if self.imap_server and self.username and self.password:
+ self.processor = Processor(self.imap_server, self.username, self.password, self.on_receive)
+ self.processor.start()
+ self.win = None
+
+ def on_receive(self, pr_str):
+ self.print_error('received payment request')
+ self.pr = PaymentRequest(pr_str)
+ if self.win:
+ self.win.emit(SIGNAL('email:new_invoice'))
+
+ def new_invoice(self):
+ self.win.invoices.add(self.pr)
+ self.win.update_invoices_list()
+
+ @hook
+ def init_qt(self, gui):
+ from electrum_gui.qt.util import ThreadedButton
+ self.win = gui.main_window
+ self.win.connect(self.win, SIGNAL('email:new_invoice'), self.new_invoice)
+
+ self.send_button = EnterButton(_('Send'), self.send)
+ self.win.receive_buttons.insertWidget(1, self.send_button)
+
+ def send(self):
+ addr = str(self.win.receive_address_e.text())
+ message = unicode(self.win.receive_message_e.text())
+ payment_request = self.win.make_payment_request(addr)
+
+ if not self.win.save_payment_request():
+ return
+
+ recipient, ok = QtGui.QInputDialog.getText(self.win, 'Send request', 'Send request to:')
+ if not ok:
+ return
+
+ recipient = str(recipient)
+ self.print_error('sending mail to', recipient)
+ try:
+ self.processor.send(recipient, message, payment_request)
+ except BaseException as e:
+ self.win.show_message(str(e))
+ return
+
+ self.win.show_message(_('Request sent.'))
+
+
+ def requires_settings(self):
+ return True
+
+ def settings_widget(self, window):
+ return EnterButton(_('Settings'), self.settings_dialog)
+
+ def settings_dialog(self, x):
+ from electrum_gui.qt.util import Buttons, CloseButton, OkButton
+
+ d = QDialog(self.window)
+ d.setWindowTitle("Email settings")
+ d.setMinimumSize(500, 200)
+
+ vbox = QVBoxLayout(d)
+ grid = QGridLayout()
+ vbox.addLayout(grid)
+
+ grid.addWidget(QLabel('Server'), 0, 0)
+ server_e = QLineEdit()
+ server_e.setText(self.imap_server)
+ grid.addWidget(server_e, 0, 1)
+
+ grid.addWidget(QLabel('Username'), 1, 0)
+ username_e = QLineEdit()
+ username_e.setText(self.username)
+ grid.addWidget(username_e, 1, 1)
+
+ grid.addWidget(QLabel('Password'), 2, 0)
+ password_e = QLineEdit()
+ password_e.setText(self.password)
+ grid.addWidget(password_e, 2, 1)
+
+ vbox.addStretch()
+ vbox.addLayout(Buttons(CloseButton(d), OkButton(d)))
+
+ if not d.exec_():
+ return
+
+ server = str(server_e.text())
+ self.config.set_key('email_server', server)
+
+ username = str(username_e.text())
+ self.config.set_key('email_username', username)
+
+ password = str(password_e.text())
+ self.config.set_key('email_password', password)
+
+