邮件发送
前言
仔细想想,关于邮件发送的任务也是从年前拖到了年后。看样子拖不下去了,我这周要将其搞定收工。然后,腾出手来做其他的事情。
正文
我觉得,一个项目迭代了两年,就会存在各种各样的”垃圾”,比如,发送邮件存在xx种形式。针对邮件的功能,在项目中做了一番调查:
- mailchimp-api
- resque_mailer
- Action Mailer
- SendCloud
备注: 邮件的事情,咨询了相关人之后,得知mailchimp-api可能就不需要了。
Rails 使用 Action Mailer实现邮件发送,邮件程序和视图,ActionMailer::Base
,与控制器类似,app/mailers
和app/views
,简单的例子程序如下:
class UserMailer < ActionMailer::Base
default from: 'notifications@example.com'
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
mail(to: @user.email, subject: 'Welcome to My Awesome Site')
end
end
邮件程序不知道请求的上下文,需要指定host,使用xxx_url
,或使用url_for
时,指定only_path: false
。
Action Mailer中也可设置before_action
、after_action
和 around_action
这些过滤器。
Action Mailer继承自AbstractController,控制器中的帮助方法均可使用。
Mailer选项最好在环境相关的文件(environment.rb, production.rb)中进行配置。
注册以及验证邮箱之类,通过Rails自带的ActionMailer程序进行发送的,
sendcloud
向用户批量发送邮件使用的第三方的服务 - sendcloud,发送使用了其web api的方式,使用的sendcloud类是自定义的。
在github上搜了一下,sendclound的相关的ruby项目还挺多的。大概有5个。
调用方式: SMTP和WEBAPI(支持HTTPS)。
操作流程:
- 写程序,调接口,传数据
- 请求成功,数据处理( 排队调度, 速率控制, 变量替换, 追踪 )
- 处理结束,发送邮件( outbound )
- outbound投递邮件
邮件类型: 触发和批量
API_USER: 调用接口发信的帐号,具有类型、发信域名、追踪选项等
API_KEY: 可重置,可共用
发信域名: 配置VERIFY_KEY
,SPF
,MX
,CNAME
,DKIM
。感觉好复杂。
看了好多天,没实在感,找了个方式测试一下:
RestClient.post "https://sendcloud.sohu.com/webapi/mail.send.json",
:api_user => "xxx",
:api_key => "xxxx",
:from => "no-reply@tophold.com",
:fromname => "天厚投资",
:to => "xiajian@tophold.com",
:subject => "测试",
:html => "这是一个测试"
执行了一下,居然成功了,看到效果,有了继续下去的操作勇气。又定义了一个获取列表的函数,并发现一个问题,API文档 中描述可以使用get请求,实际上是使用get请求列表的返回结果如下:
{"message":"error","errors":["Bad username / password!"]}
而post请求却是正常的,仔细想想,使用get
请求存在诸多的不安全性,api_user
和api_key
很容易被抓包。
备注: 找到了一个关于sendcloud的gem包,正在由于是用自制的还是使用gem包。感觉上gem包要复杂些,自写的重复代码太多。
搞了半天,结果发送一周未登录的邮件居然不是通过sendcloud发送的,坑爹啊。
编写邮件view的注意点:
- 所有的url必须是绝对地址
- 所有的样式必须是直接写在body中。
smtp的配置
配置使用smtp的服务,代发所有的邮件,最重要的就是smtp的配置。下面列出一些配置:
官方给出的配置:
Mail.defaults do
delivery_method :smtp, {
:address => "smtpcloud.sohu.com",
:port => 25,
:user_name => "api_user",
:password => "api_key",
:authentication => 'login'
}
end
自己使用的配置:
ActionMailer::Base.smtp_settings = {
:address => "smtpcloud.sohu.com",
:port => 25,
:authentication => :login,
:domain => 'tophold.com',
:user_name => "xxx",
:password => "xxx"
}
就这个简单的配置,拖了好几个月。
遇到问题
An SMTP From address is required to send a message. Set the message smtp_envelope_from, return_path, sender, or from address.
搞了半天,才知道是修改问题后,Rake任务不自动加载代码,然后,我就一直在纠结为何总是发不出去,最后问了前辈之后,才知道为何。重启了一下,就好。唉,又一个上午没有了。不过,对如何发送和测试邮件有了整体的思路,以后再做相关的工作,就轻松了,测试果然太重要了。
启动后台邮件任务: rake resque:work QUEUE="async_mailer"
,在redis中生成了名为”resque:tophold:queue:async_mailer”的list类型,其中resque:tophold
是所谓的命名空间。
测试发送邮件:
u = User.where( email: "xxx@qq.com").first
NoticeMailer.login(u.id).deliver # 邮件的发送,需要使用deliver方法,login是邮件控制器的动作
此刻,我对如何使用和启动后台任务,有了更加深入的的了解,并且,有了可评估和测试的环境,感觉相当不错。
针对全体用户发送邮件,qq链接邮件种类的问题(qq连接的用户邮件根本发不出去)。
查询后发现,已有用户中,居然有39808个用户是通过qq授权,且未验证邮箱的。然后,未验证的邮箱发送的结果就是这样的。
sendcloud一直将xx@example.com
这种类型邮件地址设置为请求状态,我把这个问题向sendcloud的客服反馈了一下,敲字敲到手疼。
mail的视图,不能使用视图的辅助方法,只能使用图片的绝对路径,这是硬伤。
后记
近来,觉得自己十分的平庸,干啥啥不成。因为又有一件事情干到一半,然后放在一边了,比如邮件的这次任务。
我觉得,我这种性格还是有一定的好处的,犹如单核多进程一般的,乱序执行,话说,进程间切换开销很大的说。
被市场部的追着要邮件发送的功能了,拖不下去了。这个邮件召回的任务,我拖了3个月,有没有很牛叉的感觉。
我觉得,邮件系统这件事,还是很有搞头的。 而且,我觉得我做的这件事情,重复的太多,一点都不最佳实践,但是,自己也没有作出什么更好的改进。
傲娇的使用Disqus