w9-网络遗书demo

后端邮件服务设计

有了前面关于时间的写法、比较、筛选方法,剩下的就好写了:

还是梳理逻辑,总共两个函数,其一用于筛出心跳确认邮件的发送:

  1. 获取当前日期,将它输入查询语句
  2. 根据输入筛选出所有查询到的的数据种抽取:用户名、用户联系邮箱
  3. 向被筛选出来的对象邮箱发送确认邮件。

另一个用于向亲属发送遗嘱,这个先向后放:

  1. 获取当前日期,将它输入查询语句
  2. 根据输入筛选出所有查询到的的数据种抽取:用户名、用户联系邮箱、遗嘱、遗嘱和联系人对应关系、亲属联系邮箱。
  3. 向北筛选出的对象邮箱发送遗嘱文件。

另外为了专门运行测试,单独设置一个测试用邮箱:

用户名:[email protected] 密码:P@ssw0rdP@ssw0rd

# 导入时间模块
import time

# 获取当前时刻时间戳
timenow = time.time()

# 定义查询时间函数,获取
livecheck = collection.find({"heatbeatSync":{"$lte":timenow},"heatbeatFinal":{"$gte":timenow}},{'userID':1,'name':1,'heatbeatmail':1})

# 显示查询结果
print livecheck

for i in livecheck:
    userID = i.get('userID')
    name = i.get('name')
    mailaddr = i.get('heatbeatmail')
    livecheck(userID,name,mailaddr)




# 邮件相关
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr

import smtplib


# 邮件服务测试
def livecheck_mail(userID,name,mailaddr):

    def _format_addr(s):
        name, addr = parseaddr(s)
        return formataddr((Header(name, 'utf-8').encode(), addr))

    from_addr = 'whenmgonetest'
    password = 'P@ssw0rdP@ssw0rd'
    to_addr = mailaddr
    smtp_server = 'smtp.163.com'

    msg = MIMEText('<h2>亲爱的' + name + ',whenmgone向您个安!</h2>' 
        + '\n' + '<form action="#" method="POST"><button type="submit">平身罢</button></form>',
         'html',  'utf-8')
    msg['From'] = _format_addr('whenmgone <%s>' % from_addr)
    msg['To'] = _format_addr(name + ' <%s>' % to_addr)
    msg['Subject'] = Header('whenmgone定期心跳', 'utf-8').encode()

    server = smtplib.SMTP(smtp_server, 25)
    server.set_debuglevel(1)
    server.login(from_addr, password)
    server.sendmail(from_addr, [to_addr], msg.as_string())
    server.quit()

实验数据

为了能够测试,首先必须设计几条合理的数据格式备用,上回的数据都是凑合的,我打算这回发挥些当年的文艺中二余热,设计几个典型用户试一下:

  1. 张向阳,一个山西汉字,北漂一族,在互联网公司coding,独子单身狗,北京有同学无亲人,每年过年回家一次。爱工作,公司环境又好,恨不得吃住都在公司,但平时加班非常狠,生活也极其不规律,比较毕业前明显发福很多。生活比较追求流行,接收新鲜事务很快,最近几年随着各种宝的火热,拿着自己攒的钱开始尝试着到处投资,股票、p2p、余额宝、比特币什么都有尝试,在15年股灾后,虽然嘴上说决心再不进股市,但还是留了一些,账户十分分散,看到朋友有人用网络遗嘱服务觉得有意思,于是自己也注册了一个。

  2. 唐晓楠,一个20出头的四川姑娘,性格直爽但精明,敢想又敢干,从小到大做过各种工作,目前在鼓浪屿做导游,虽然收入高但还是月光族。和男朋友异地,准备明年结婚,于是开始逐渐攒钱,主要的钱都是放在余额宝和银行自己的宝里面,微信账户也有一些钱,用来做支付和发红包用,但自己并不清楚到底都有多少,属于赚钱没数,花钱没边的。因为男朋友注册了网络遗书服务,还告诉她注意收遗书,于是图新鲜也注册了个。

  3. 宋旭涛,年纪不到40,在银行工作,在一个二线省分行做信贷审批,留学生背景,本来是在总行工作,但因为要照顾家里老人,所以最终留在了家乡。用的银行卡主要是自己行里的,自己的钱主要投的是银行推荐的理财产品,而且也有父母和亲属的钱很多也拜托他一起帮忙投放,有一笔比较大额的是亲朋好友一起拼的信托,找的熟人投出去的。这些钱中,风险最大的是自己一少部分投资的一些超过10%的一年期债权,网络上的p2p什么的觉得根本不靠谱也不想投。自己身体并不很好,而且这些年发福的厉害,又缺乏运动,最近一次体检查出血糖高,自己于是打算开始从饮食上入手开始注意。最近办公室里有人讨论关于网络遗嘱的事,他觉得可行,但对平台的安全性十分质疑,最终还是注册了。

有了这样的背景,可以开始设计他们的平台数据了:

张向阳用例

id: yoga password:P@ssw0rdZXY@whenmgone name:张向阳 phone:18600563873

note01.content:

爸妈,别太难过,这几年在外面漂回家回的可能太少了,没能照顾到您们,您别介意。 我在北京过的挺好的,公司同事对我都不错,如果我挂了那也肯定不是过劳死,妈您可千万别跟公司起误会。 我这个留言主要是想告诉您二老,我有好些钱都投在了一些网络账户上,您拿着我的手机可千万别扔,登录里面好几个App里面都把钱取出来吧,我下面一一告诉您怎么取:

  1. 支付宝密码是*。。。
  2. 还有工商银行那个。。。。
  3. 另外我有个京东账户,这个您把我弟找来,让它告诉您怎么操作,到时候密码您输入**
  4. 还有个宜信,那个只能到了时候才能取,这个您看*
  5. 然后有个华泰的账号,这个您找舅舅,让它告诉您怎么把这个兑出来,您千万告诉他里面有个**建议长期持,那个特别好。。。

note01.link:['content01']

contact01.mail:'[email protected]' contact01.phone:'15019371635' contact01.name: '赵慧珍'

heatbeatmail:'[email protected]'

heatbeatRate:7,

heatbeatDelay:7,

heatbeatUpdate:1450110040.0,

heatbeatSync:1450714840.0,

heatbeatFinal:1451319640.0,

唐晓楠用例

id: tangnans password:75643871T name:唐小楠 phone:13800583746

note01.content:

老公,如果你看到了这个,那我可能已经死了,不管咱们结没结婚,对你的好要记挂我一辈子哈。 你要是找别人也行,可千万别太快啊,要不让我爸怎么想。 哎呀,我实在写不下去了,没了我你可怎么活呢,做饭也不会,还天天出去吃的乱七八糟的。 爱你的楠

note01.link:['content01']

contact01.mail:'[email protected]' contact01.phone:'15028376153' contact01.name: '汪大勇'

heatbeatmail:'[email protected]'

heatbeatRate:14,

heatbeatDelay:14,

heatbeatUpdate:1450110040.0,

heatbeatSync:1450714840.0,

heatbeatFinal:1451319640.0,

宋旭涛用例

id: YonySong password:19780921 name:宋旭涛 phone:13276543939

note01.content:

丽芳,最终还是没想到要先走一步,不过好在有个这样的邮件服务,能让我最后还能和你聊些心里话,也算是件挺好的事。 咱们在一起都过了10年了,但是不知道是不是因为工作和生活的压力,反而让我们越来越疏远,再也回不到当初谈理想搞浪漫的状态。虽然我们之间已经沉默到连架都懒得吵了,但对我来讲你永远是最重要的人,和你结婚一起生活这么多年我最终还是不后悔。

没能看着宝婷长大是我最大的遗憾,上次学校活动我没参加确实是我的错,我道歉,千万不要为了这件事再记恨我了。不过我也确实对自己失望,混了这么多年都最终还是没能把宝婷办到更好的学校里面去,但这件事情我还是期望你再想想办法,这对宝婷是很重要的事,千万不要因为不好弄就不办了,学校那边该打点的还是要打点,这不是该省钱的地方,切记!

另外除了咱们家的银行卡之外,我还有一张卡里面存了些货币基金,大概在200w左右,密码是你生日,不到万难时候最好别取,一直存着就行了。还有老舅有一笔40w,你弟的20w,还有咱们家的40w我合在了一起,交给张扬去投信托了,留了张借据就在红木柜子倒数第二层有个牛皮纸袋里,日期到了的时候记得找张扬兑。

真正写遗嘱的时候才发现好多话真应该和你当面说,我期望咱们家都平平安安的谁都看不到这封信是最好的结果,就这些罢!

note01.link:['content01']

contact01.mail:'[email protected]' contact01.phone:'15173649384 contact01.name: '徐丽芳'

heatbeatmail:'[email protected]'

heatbeatRate:30,

heatbeatDelay:30,

heatbeatUpdate:1450110040.0,

heatbeatSync:1450714840.0,

heatbeatFinal:1451319640.0,

这样数据就基本准备好了

封装时间计算

我把时间计算封装在一个类里面集中运算,这样只要返回时间戳就ok了

# -*- coding: UTF-8 -*-
'''
* 用于whenmgone的demo原型测试(时间计算)
* [email protected] 
* 2015.12.5
'''
# 引入os模块
import os
# 引入time模块
import time
# 引入datatime模块
from datetime import datetime,timedelta

# 设置时间计算模块儿
class TimeCompute(object):
    """用于计算遗书服务更新时间"""
    # 初始化模块儿参数心跳频率和时间时间
    def __init__(self, heatbeatrate,heatbeatdelay):
        self.heatbeatrate = heatbeatrate
        self.heatbeatdelay = heatbeatdelay
        self.timenow = datetime.now()
    # 最后更新时间戳
    def heatbeatUpdate(self):
        return time.mktime(self.timenow.timetuple())
    # 下次同步时间戳
    def heatbeatSync(self):
        _timesync = self.timenow + timedelta(days=self.heatbeatrate)
        return time.mktime(_timesync.timetuple())
    # 最晚延时时间戳
    def heatbeatFinal(self):
        _timefinal = self.timenow + timedelta(days=self.heatbeatrate+self.heatbeatdelay)
        # _timefinal = _timenow + timedelta(days=heatbeatdelay)
        return time.mktime(_timefinal.timetuple())

# 时间计算用例
a=TimeCompute(7,7)
print a.heatbeatUpdate()
print a.heatbeatSync()
print a.heatbeatFinal()

这样时间参数的封装也ok了,下一步,我需要把查询和发送邮件想办法连起来

首先我把两种邮件发送函数写好:

# -*- coding: UTF-8 -*-
# 引入sys模块,并将默认字符格式转为utf-8
import sys
sys.path.append("./")
reload(sys)
sys.setdefaultencoding( "utf-8" )

# 邮件相关
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr

import smtplib



# 邮件服务测试——心跳检测
def livecheck_mail(userID,name,mailaddr):

def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

from_addr = '[email protected]'
password = 'awhhatnazgnrjsya'
to_addr = mailaddr
smtp_server = 'smtp.163.com'

msg = MIMEText('<h2>亲爱的' + name + ',whenmgone向您个安!</h2>' 
    + '\n' + '<form action="#" method="POST"><button type="submit">平身罢</button></form>',
     'html',  'utf-8')
msg['From'] = _format_addr('whenmgone <%s>' % from_addr)
msg['To'] = _format_addr(name + ' <%s>' % to_addr)
msg['Subject'] = Header('whenmgone定期心跳', 'utf-8').encode()

server = smtplib.SMTP(smtp_server, 25)
server.set_debuglevel(1)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string())
server.quit()


# 邮件服务测试——遗嘱发送
def notesend_mail(userID,name,contactname,mailaddr):

    def _format_addr(s):
        contactname, addr = parseaddr(s)
        return formataddr((Header(contactname, 'utf-8').encode(), addr))

    from_addr = '[email protected]'
    password = 'awhhatnazgnrjsya'
    to_addr = mailaddr
    smtp_server = 'smtp.163.com'

    msg = MIMEText('<h2>' + contactname + ':<br>您好,我们受 <b>' + name +'</b> 委托,向您发送他最后的留言,请点击如下链接进行查收!</h2>' 
        + '\n' + '<form action="#" method="POST"><button type="submit">留言</button></form>',
         'html',  'utf-8')
    msg['From'] = _format_addr('whenmgone <%s>' % from_addr)
    msg['To'] = _format_addr(contactname + ' <%s>' % to_addr)
    msg['Subject'] = Header('whenmgone网络遗嘱', 'utf-8').encode()

    server = smtplib.SMTP(smtp_server, 25)
    server.set_debuglevel(1)
    server.login(from_addr, password)
    server.sendmail(from_addr, [to_addr], msg.as_string())
    server.quit()

然后做出检查数据库,并获取到对象的模块儿:

# 导入pymongo模块
import pymongo
# 设置数据库地址
client = pymongo.MongoClient('172.16.191.163', 27017)
# 设置数据库名
db = client['demodb']
# 设置表名
collection = db['demotable']

# 导入时间模块
import time

# 获取当前时刻时间戳
timenow = time.time()

# 获取所有的该发送定时心跳的对象
livecheck = collection.find({"heatbeatSync":{"$lte":timenow},"heatbeatFinal":{"$gte":timenow}},{'userID':1,'name':1,'heatbeatmail':1})

# 获取所有的该发送遗嘱的对象
deathcheck = collection.find({"heatbeatFinal":{"$lte":timenow}},{'userID':1,'name':1,'heatbeatMail':1,'contact01':1})

并最终建立检查并发送的循环:

# 检查心跳并发送主循环
for i in livecheck:
    userID = i.get('userID')
    name = i.get('name')
    mailaddr = i.get('heatbeatMail')
    print userID,name,mailaddr
    livecheck_mail(userID,name,mailaddr)

# 检查无回应并发送主循环
for i in deathcheck:
    userID = i.get('userID')
    name = i.get('name')
    mailaddr = i.get('heatbeatMail')
    contact01 = i.get('contact01').get('name')
    print userID,name,mailaddr,contact01
    notesend_mail(userID,name,contact01,mailaddr)

这样一个可用的检查到期并循环发送邮件模块就写好了,但并不算完美,这个脚本需要每天手动执行一次,相对完善的方式是想办法做一个每天定期的执行查询循环,发送邮件我找到了一个sched模块,这个我打算放在后面在做,我把这个函数封装在daily.py里面,下周主要任务把前端做好看。

最后,我把数据库检查函数设定成能检索到自己的模式,发送邮件做测试

屏幕快照 2015-12-21 00.08.20.png 屏幕快照 2015-12-21 00.08.45.png

至此,demo版本完全可用,demo成功