摘要
正在生成中……
我最近在玩 zlibrary , 它提供了很多免费的电子书,可以点击按钮将当前电子书发送到 gmail ,这个功能是免费的,另外还有一个发送到亚马逊kindle个人文档邮箱的服务,需要高级用户,或者PREMIUM:
Zlib无法访问时,参考这个页面获得更多镜像站:
https://topstip.com/the-worlds-largest-digital-library-z-library-newly-available-official-site-and-mirror/
![](https://photo.cellmean.com/i/2024/05/22/8rl9-0.png)
但我想了想,好像用mailgun也能实现这个高级用户的功能,我的想法是:先把电子书发送给gmail, 在gmail设置收信规则,将从zlibaray收到的带电子书附件的邮件转给mailgun, 然后mailgun设置收信的路由规则,由mailgun存储邮件并通知我的laravel api,我的api去读取下载mailgun服务器存储的邮件,并使用我自己的邮箱地址将其发送到kindle个人文档邮箱。
Why 为什么会用这么辗转的方案 ?
至于为什么不设置gmail直接转发,是因为gmail设置转发需要给转发邮箱发一封确认信,点击内容中的确认链接后才能开始转发。而kindle的文档邮箱我是无法操作的,也就无法确认,自动转发无法工作。不过mailgun可以通过查看日志得到这封确认邮件的内容和确认接受的链接。
至于为什么不使用mailgun直接转发到kindle文档邮箱,原因是mailgun用来发送邮箱的地址是动态的,但在kindle个人文档里,你需要添加一个 确定的 受信任的邮箱,对一个动态变化的邮箱地址是没办法的。
于是只有两种方式,通过gmail或者mailgun获取邮件内容,使用一个确定的邮箱地址作为发件人将这封邮件重新发到个人文档。
如果操作gmail, 有两种方式取得邮件内容,一是通过gmail api获取,但是这玩意需要oauth应用取得token,麻烦,另一种用imap或者pop3读取gmail上的邮件,需要独立的应用密码,是一个备选方案。
如果操作mailgun,可以在路由中让它存储邮件,免费版保留两天,足够了,而且它还有webhook,可以触发我的api去它的存储读取信件内容,比较主动,关键是比较简单。而且如果使用读取gmail邮件,也需要先用mailgun的webhook去触发我的api。
Wait a minite,这里有一个坑
我在mailgun的Api keys 看到的列表上的字符,我以为就是api key,测试半天都是401,我又怀疑是不是账户不对,邮箱
,Account Name
, Full name
全试了一遍都不对。
![](https://photo.cellmean.com/i/2024/05/21/fnc9zq-0.png)
原来它那串字符根本不是api key,而是key id,成功误导我。真正的 api key 只会显示一次,就是在生成之后要即刻保存,这个倒正常,一般生成token或者密钥都是这般,但尼玛这个key id 有必要搞得这么像api key本体吗?
而且又是用户名,又是邮箱,又是Full name ,最后又加了一个sinchID ,文档说username其实就是邮箱地址。
鉴于我忘记之前生成的密钥,只能重新生成了一个,基本用法就是这样,比如读取events
:
curl -i -X GET -u 登录邮箱:你的apiKey 'https://api.mailgun.net/v3/邮箱域名/events'
可以用你的测试域名如:
sandbox12341234.mailgun.org
我的mailgun注册得比较早,后来的需要短信验证,但国内手机似乎已经收不到验证短信了,至少我的是这样。
找用户名和密码我最后是参考这个文档:
我在哪里可以找到我的 API 密钥和 SMTP 凭证?– Mailgun 帮助中心 --- Where can I find my API keys and SMTP credentials? – Mailgun Help Center
开工
mailgun
提供了php的SDK,github地址在此。功能很全面,然而我并不需要这么庞大的库。我做的只是读取那个 notify webhook
传来的信息,获取电子书名称,下载电子书到本地,然后重新发送该电子书给kindle 就行了。
测试捕捉 notifiy webhook
传到的内容:
Route::post('/zlib-gmail-mailgun-notify', function(Request $request){
$data = var_export($request->all(), true);
$filename = "zlib-gmail-mailgun-notify-" . now()->format('Ymd-His') . ".log";
Storage::put($filename, $data);
});
触发后会得到一个数组,其中最重要的两个字段是这两个,即附件列表和邮件内容。
![](https://photo.cellmean.com/i/2024/05/21/swgdzn-0.png)
其中附件字段内容如下,
'attachments' => '[{"name":"RabbitMQ实战:高效部署分布式消息队列 (汪佳南) (Z-Library).epub","content-type":"application/epub+zip","size":14588418,"url":"https://storage-us-west1.api.mailgun.net/v3/domains/sandboxb1234.mailgun.org/messages/BAE1234/attachments/0"}]',
注意:这是一个字符串而不是数组, 我在这里又踩了个坑,需要做一次json_encode
才是数组, 然后取数组第一个元素,才是电子书的信息,其中url
是电子书的下载地址,需要使用前面的用户名和apiKey去下载回来。
用 curl
请求是这样的:
curl -i -X GET -u 登录邮箱:你的apiKey 'https://storage-us-west1.api.mailgun.net/v3/domains/sandboxb1234.mailgun.org/messages/BAE1234/attachments/0'
开发体验和思考
代码很简单,但是写完测试没有成功,又测试了很多次,发现各种问题,直到我一天10次发送电子书的配额满了,使用log里的内容测试,终止成功了。比如这本就是用 api 成功推送上去的。
![](https://photo.cellmean.com/i/2024/05/21/12rnkc1-0.png)
如果正常地本地开发,应该不会这么一波三折,主要还是远程开发的体验,实在是一言难尽,晚高峰网络拉胯了,无论是使用 vscode 连接ssh连接,还是在code server 网页版,没有装php Intellisense 和 PHP Namespace Resolver 的 vscode 扩展时,连变量名没拼对vscode 也不会给下划线警告,没有声明就使用的类也没有警告,这些平时在编辑器就可以看到的错误,要等我运行代码再看laravel的log才发现,着实有点烦。
如果安装扩展,国内连美帝服务器,安装扩展转圈了半天也没装上,基本不可用。
以前我很推崇远程开发,恨不得把本地所有的代码都放在服务器远程连接来写,但我现在对远程开发这事着实有点ptsd了。远程肯定是未来的趋势,但是这么痛苦也是没想到的,可能是我的姿势不对,得想个办法。在本地写,然后推送上去,或者本地端口映射到国内的主机,用nps或者cloudflare tunnel之类的 ,反正我不想在远程服务器上直接写了,特别是国外的服务器。