[Add] Email engine for sending email message.

This commit is contained in:
vn.py 2019-01-12 10:44:53 +08:00
parent 6e1d90b327
commit 242a97a2b2
5 changed files with 117 additions and 4 deletions

View File

@ -5,6 +5,10 @@ import logging
from datetime import datetime from datetime import datetime
from abc import ABC from abc import ABC
from typing import Any from typing import Any
from threading import Thread
from queue import Queue, Empty
import smtplib
from email.message import EmailMessage
from vnpy.event import EventEngine, Event from vnpy.event import EventEngine, Event
@ -62,6 +66,7 @@ class MainEngine:
""" """
self.add_engine(LogEngine) self.add_engine(LogEngine)
self.add_engine(OmsEngine) self.add_engine(OmsEngine)
self.add_engine(EmailEngine)
def write_log(self, msg: str): def write_log(self, msg: str):
""" """
@ -135,6 +140,9 @@ class MainEngine:
Make sure every gateway and app is closed properly before Make sure every gateway and app is closed properly before
programme exit. programme exit.
""" """
for engine in self.engines.values():
engine.close()
for gateway in self.gateways.values(): for gateway in self.gateways.values():
gateway.close() gateway.close()
@ -157,6 +165,10 @@ class BaseEngine(ABC):
self.event_engine = event_engine self.event_engine = event_engine
self.engine_name = engine_name self.engine_name = engine_name
def close(self):
""""""
pass
class LogEngine(BaseEngine): class LogEngine(BaseEngine):
""" """
@ -398,3 +410,66 @@ class OmsEngine(BaseEngine):
if order.vt_symbol == vt_symbol if order.vt_symbol == vt_symbol
] ]
return active_orders return active_orders
class EmailEngine(BaseEngine):
"""
Provides email sending function for VN Trader.
"""
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
""""""
super(EmailEngine, self).__init__(main_engine, event_engine, "email")
self.thread = Thread(target=self.run)
self.queue = Queue()
self.active = False
self.main_engine.send_email = self.send_email
def send_email(self, subject: str, content: str, receiver: str = ""):
""""""
# Start email engine when sending first email.
if not self.active:
self.start()
# Use default receiver if not specified.
if not receiver:
receiver = SETTINGS["email.receiver"]
msg = EmailMessage()
msg["From"] = SETTINGS["email.sender"]
msg["To"] = SETTINGS["email.receiver"]
msg["Subject"] = subject
msg.set_content(content)
self.queue.put(msg)
def run(self):
""""""
while self.active:
try:
msg = self.queue.get(block=True, timeout=1)
with smtplib.SMTP_SSL(SETTINGS["email.server"],
SETTINGS["email.port"]) as smtp:
smtp.login(
SETTINGS["email.username"],
SETTINGS["email.password"]
)
smtp.send_message(msg)
except Empty:
pass
def start(self):
""""""
self.active = True
self.thread.start()
def close(self):
""""""
if not self.active:
return
self.active = False
self.thread.join()

View File

@ -7,9 +7,14 @@ from logging import CRITICAL
SETTINGS = { SETTINGS = {
"font.family": "Arial", "font.family": "Arial",
"font.size": 12, "font.size": 12,
"log.active": True, "log.active": True,
"log.level": CRITICAL, "log.level": CRITICAL,
"log.console": True, "log.console": True,
"log.file": True "log.file": True,
"email.server": "smtp.qq.com",
"email.port": 465,
"email.username": "",
"email.password": "",
"email.sender": "",
"email.receiver": ""
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -103,6 +103,13 @@ class MainWindow(QtWidgets.QMainWindow):
self.restore_window_setting self.restore_window_setting
) )
self.add_menu_action(
help_menu,
"测试邮件",
"email.ico",
self.send_test_email
)
self.add_menu_action( self.add_menu_action(
help_menu, help_menu,
"关于", "关于",
@ -219,3 +226,9 @@ class MainWindow(QtWidgets.QMainWindow):
""" """
self.load_window_setting("default") self.load_window_setting("default")
self.showMaximized() self.showMaximized()
def send_test_email(self):
"""
Sending a test email.
"""
self.main_engine.send_email("VN Trader", "testing")

View File

@ -310,6 +310,11 @@ class TickMonitor(BaseMonitor):
"cell": BaseCell, "cell": BaseCell,
"update": False "update": False
}, },
"exchange": {
"display": "交易所",
"cell": BaseCell,
"update": False
},
"last_price": { "last_price": {
"display": "最新价", "display": "最新价",
"cell": BaseCell, "cell": BaseCell,
@ -419,6 +424,11 @@ class TradeMonitor(BaseMonitor):
"cell": BaseCell, "cell": BaseCell,
"update": False "update": False
}, },
"exchange": {
"display": "交易所",
"cell": BaseCell,
"update": False
},
"direction": { "direction": {
"display": "方向", "display": "方向",
"cell": DirectionCell, "cell": DirectionCell,
@ -466,6 +476,11 @@ class OrderMonitor(BaseMonitor):
"cell": BaseCell, "cell": BaseCell,
"update": False "update": False
}, },
"exchange": {
"display": "交易所",
"cell": BaseCell,
"update": False
},
"direction": { "direction": {
"display": "方向", "display": "方向",
"cell": DirectionCell, "cell": DirectionCell,
@ -540,6 +555,11 @@ class PositionMonitor(BaseMonitor):
"cell": BaseCell, "cell": BaseCell,
"update": False "update": False
}, },
"exchange": {
"display": "交易所",
"cell": BaseCell,
"update": False
},
"direction": { "direction": {
"display": "方向", "display": "方向",
"cell": DirectionCell, "cell": DirectionCell,