通过 PHP 向许多用户发送邮件的安全方法
让我解释一下标题中的意思。假设我正在为一个网上商店/目录创建一个小型电子商务系统。客户可以选择是否希望收到新闻通讯。如果他们这样做,那么从逻辑上讲,应该在新闻通讯形成并准备就绪后立即发送新闻通讯。
当然,可以简单地通过从数据库中获取所有指定的用户电子邮件并使用 for
循环通过循环中的 mail
函数发送邮件来完成,但问题是我是告诉,这是不好的做法。简单且不便宜的方法是购买互联网服务来发送新闻通讯,但是对于 php 程序员来说需要什么呢?
所以请问各位战友,从你们的角度来看,可能有什么解决办法呢?
注意!您可能不会相信我,但这不是为了发送垃圾邮件。
UPD:我可能对自己的解释是错误的,但我想听到一个解决方案,不仅关于发送邮件的正确方式,而且关于正确的投递。因为并非所有发送的邮件都会被送达。
当然,还有一些不可预测的原因。例如,在途中的某个地方,有些东西坏了,邮件丢失了(如果可能的话),但也有其他原因可能受到服务器或其他地方的影响。也许需要和房东谈谈?
Let me explain what I mean in my title. Let's say, that for example I'm creating a small e-commerce system for one web shop/catalog. There's a possibility for customers to choose, do they wish to receive newsletters or not. If they do, then logically thinking the newsletters should be send immediately as the newsletter is formed and ready.
Of course it can be done simple by fetching all specified user e-mails from database and using for
cycle to send mail via mail
function in loop, but problem is that I was told, that this is bad practice. The simple and not cheap way would be purchasing internet service for sending newsletters, but what for the php programmer is needed, then?
So I ask you humble comrades, what from your point of view might be a solution?
NB! You probably won't believe me, but it is not for spamming.
UPD: I might have explained myself wrong, but I would like to hear a solution not only about the correct way to send mail, but also about the correct delivery. Since not every mail send is always delivered.
Of course there are some reasons, which are unpredictable. For example someplace along the way something broke and mail was lost (if such thing is possible), but there are also other reasons which are influenced maybe from server or elsewhere. Maybe there is need to talk with hoster about it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
尽管我不会将其作为网络请求/HTTP 流程的一部分,但您没有理由不能用 PHP 编写它。我已经成功实现了每封邮件可容纳 500,000 个订阅者(取决于可用的本地数据,因为这是一个特定于位置的项目)。这是一个内部项目,因此不幸的是没有适合您的代码/包,但我遇到了一些提示:
设置交付
filter_var($email, FILTER_VALIDATE_EMAIL);
对订阅者(并明显存储结果)删除了前几十万封无效电子邮件。foo@[255.255.255.255]
,因此请保持这些有效))又摆脱了很大一部分。此处的电子邮件地址并未永久禁用,但带有一个状态标志,表明它们因域名/IP 原因而被禁用。Return-Path
已设置为[电子邮件受保护]
。在收据上轻松解析,在多少次退回邮件(邮箱可能不存在、邮箱可能已满(是的,仍然是!)等)之后,您可以声明电子邮件地址不可用。提高速度
避免拒绝
abuse@
电子邮件地址是一个很好的起点,但看看您是否可以从某处挖掘出更切题的电子邮件地址。准确、诚实和完整:大约有多少订阅者拥有该 ISP 的电子邮件地址,您尝试向他们发送邮件的频率如何,您收到的错误或拒绝是什么,订阅和订阅情况如何。 unscubscribe 流程是什么样的,以及您实际向他们的客户提供的服务是什么。另外,要友善:发送这些邮件对您的业务可能非常重要,对此感到恐慌并声称遭受严重损失与他们无关。礼貌地陈述事实和愿望,并询问他们是否可以提供帮助,而不是要求解决方案,这会大有帮助。避免被标记为垃圾邮件
测量成功率
总而言之,包括所有日志记录、用户界面、每个域/电子邮件/用户的可配置设置等。我们花了大约 1.5 个人月的时间来构建和构建它。消除怪癖。与外包电子邮件相比,这可能是一项相当大的投资,也可能不是,这完全取决于数量和电子邮件的数量。业务本身。
现在,让我们开始吧,我是一个傻瓜,用 PHP 编写 MTA,我非常喜欢它(这是我编写如此大量文本的原因之一),以及极其通用的日志记录和日志记录功能。设置功能、基于故障百分比的每台主机警报等让直播变得如此简单;)
There is no reason why you couldn't write it in PHP, although I would not make it a part of a webrequest / HTTP process. I've successfully implemented for give or take 500,000 subscribers per mailing (depending on local data available, as this was a location-specific project). It was an in-house project, so unfortunately no code/package for you, but some pointers I came across:
Setting up delivery
filter_var($email, FILTER_VALIDATE_EMAIL);
over the subscribers (and storing the result obviously) got rid of the first few hundred thousand invalid emails.foo@[255.255.255.255]
, so do keep those valid)) got rid of a good portion more. The emailaddresses here are not permanently disabled, but with a status flag that indicates they're disabled because of the domain name / ip.Return-Path
was set for[email protected]
. Easily parsed on receipt, and after how many bounces (mailbox could not exist, mailbox may be full (yes, still!), etc.) you declare an emailaddress unusable is up to you.Getting speed
Avoiding rejects
abuse@
email address is a good place to start, but see if you can delve up a more to-the-point email address up from somewhere. Be precise, honest and complete: roughly how many subscribers of you have an emailaddress with that ISP, how often are you trying to mail them, what are the errors or denials you receive, how is the subscribe & unscubscribe process like, and what is the service you actually provide to their customers. Also, be nice: how vital sending those mails may be to your business, panicking about it and claiming terrible losses does not concern them. A polite statement of facts and wishes, and asking whether they can help rather then demanding a solution goes a very long way.Avoiding being tagged as spam
Measuring success rate
All in all, with all the logging, the user-interface, configurable settings per domain / email / user etc. It took us about 1,5 man-month to build & iron out the quirks. That may be quite an investment compared to outsourcing the emails, it may be not, it all depends on the volume & business itself.
Now, let the flaming begin that I was a fool to write an MTA in PHP, I for one thoroughly enjoyed it (which is one reason I wrote this huge amount of text), and the extremely versatile logging & settings capabilities, per-host alerts based on failure percentage etc. are making live oh so easy ;)
使用类似 Swiftmailer、PHPmailer 或 Zend_mail 是更好的替代品使用简单的
mail()
函数,因为它很容易被标记为垃圾邮件。邮件发送有太多问题需要考虑 - 其中大多数问题都是通过使用预先存在的库来解决的。手动发送群发电子邮件时需要解决一些问题:
使用不正确的标头。
处理退回邮件
由于电子邮件大量涌入而导致脚本超时。
编辑:
可能不是您正在寻找的答案。但是,我强烈建议您投资诸如 Campaign Monitor 或 邮件黑猩猩。由于此过程不是出于教育目的,而是出于商业目的,因此我强烈建议使用上述服务。
Using something like Swiftmailer, PHPmailer or Zend_mail are much better alternatives to using the simple
mail()
function as it can be easily marked as spam. There are simply too many issues with mailing that need to be considered - most of these are solved by using pre-existing libraries.Just a few problems that need to be addressed when sending mass emails manually:
Using incorrect headers.
Processing bounced messages
Timing out of script due to an influx of emails.
Edit:
Probably not the answer you're looking for. But, I would strongly suggest you invest in something like Campaign Monitor or Mail Chimp. Since this process is not for educational purposes, but commercial, I would strongly suggest the above services.
我收到了你的问题,但在回答之前,让我先谈谈通常的考虑。首先,我强烈建议使用 Mail Chimp 这样的服务。对于小型工作来说,它是免费的,并且有许多很酷的功能,比如跟踪有多少封电子邮件被打开、有多少被点击、有多少封发送失败……想想帮自己一个忙,不要重新发明轮子。
现在,为了了解目的,让我们来回答您的问题。
首先要记住的是确保你的清单是一个好的清单。怎么做呢?好吧,对于一个好的列表,我指的是有效的电子邮件地址列表。只需在您的页面上放置一份时事通讯表单,其中只有一个字段(可能是验证码,但我认为没有必要)。
将所有输入保存到数据库表中,其中“isValid”字段默认设置为 false,以及任何类型的唯一哈希。然后,您发送一封确认电子邮件,其中包含一个用于确认的链接(带有生成的哈希值),单击该链接将使“isValid”标志为真,以及一个取消链接(始终在您的所有电子邮件中发送此取消链接)。
这就是商店和严肃网站所做的。任何强迫您的客户/访客接收的内容都是不良道德行为(即垃圾邮件)。
第二件事,使用良好的托管服务。垃圾邮件发送者通常会使用过于廉价的服务,而主要的电子邮件服务会将来自这些地址的所有内容列入黑名单。
我知道,如果我问错了,你应该问问自己。不,我不,现在技术性的东西来了。
为什么将邮件函数放在 for 循环中是一种不好的做法?简单的。因为函数 mail 每次被调用时都会执行多个操作。 PHP,将打开与邮件服务器的连接,发送要解析的数据,请求发送,注册邮件服务器状态,关闭连接,冒泡状态以完成您调用的邮件功能并清理内存混乱。
从编程的角度来看,这种连接开销是人们所说的不好的做法。使用 SMTP/IMAP 解决方案更好,因为它优化了此过程。
在科技方面有点低迷,我看到你关于交付的问题。好吧,正如我所说,您有一些方法可以确保您的电子邮件列表足够好。但是,如果发生另一个异常,例如客户服务器断电+不间断故障怎么办?
嗯,PHP保持“请求邮件服务器发送,邮件服务器已发送”的状态。如果邮件服务器发送了您的消息,PHP 将返回 true。时期。
如果客户无法接收或拒绝,您应该检查电子邮件标题和电子邮件状态。这些位于电子邮件服务器上。再次强调,这些信息可以通过 SMTP/POP/IMAP 扩展来访问,而不是通过邮件功能来访问。
如果您想进一步了解,请阅读 IMAP 文档,搜索电子邮件类(phpclasses.org、pear 和 pecl 是最好的研究地点)。
额外提示:RFC 很有用,因为您可以更好地了解电子邮件服务器真正相互通信的内容。
额外提示 2:访问您的 gmail 或 ymail,检查您发送/接收的邮件的“完整版本”并阅读其标题。你可以和他们一起学到很多东西。
I got your question, but before replying, let's me go to usual considerations. First, I strongly recommend using a service like Mail Chimp. It's kinda free for small jobs, and has many cool features, like tracking back how many emails were open, how many were clicked, how many failed on deliver... Think about make a favor to yourself and don't reinvent the wheel.
Now, for getting to know purpose, let's go to the reply to your question.
First thing to have in mind is to enforce your list to be a good one. How to do that? Well, for a good list, I mean a valid email addresses list. Simple put a newsletter form on your page, with just one field (maybe a captcha, but I don't think it is necessary).
Save all input to a database table, with a field "isValid" set as false by default, and any kind of unique hash. Then you send a confirmation email, with a link (with the hash generated) for confimation which when clicked will make the "isValid" flag true, and a link for cancelation (ALWAYS send this cancelation link within all your emails).
This is what stores and serious sites do. Anything that force your customers/visitors to receive is a bad moral practice (ie, spam).
Second thing, use a good hosting service. Too cheap services usually are used by spammers, and major email services blacklist everything coming from those addresses.
I know, you should be asking yourself if I get your question wrong. No, I don't, technical stuff comes now.
Why is a bad practice put a mail function inside a for loop? Simple. Because function mail do several operations everytime it is called. PHP, will open a connection to mail server, send data to be parsed, ask for sending, register mail server status, close connection, bubble up status to finish the mail function you called and clean up the memory mess.
This connection overhead is the problem people state as bad practice from programming point of view. Using a SMTP/IMAP solution is better because it optimizes this process.
A little bit down on tech stuff I see your questions about delivery. Well, as I said, you have some ways to ensure you emails list is good enough. But what if another exception occurs, like having a blackout + no-break failures on customer server?
Well, PHP keeps the status of "asking mail server to send, mail server sent". If the mail server sent your message, PHP will return true. Period.
If client was unable to receive, or reject, you should check email headers and email status. These are on email server. Once again, these informations can be accessed with SMTP/POP/IMAP extensions, not with mail function.
If you wanna go further, read IMAP docs, search for email classes (phpclasses.org, pear and pecl are best places to look into).
Extra tip: RFCs can be useful, as you can understand better what email servers really talks to each other.
Extra tip 2: Access you gmail or ymail and check for your sent/received messages for their "full version" and read its headers. You can learn a lot with them.
通过 SMTP 身份验证: http://www.cyberciti .biz/tips/howto-php-send-email-via-smtp-authentication.html
Via SMTP Authentication: http://www.cyberciti.biz/tips/howto-php-send-email-via-smtp-authentication.html
只需使用 PHP Mail 并研究 IMF 以及如何构建可以附加第四个的自定义标头参数,exmaple
来源:http://php.net/manual/en/function。邮件.php
Just use PHP Mail and study IMF and how to build custom headers you can attach the fourth parameter, exmaple follows
Source: http://php.net/manual/en/function.mail.php
创建一个邮件队列子系统,其中可能包括 mail_queue、mail_status、mail_attachments、mail_recipients 和 mail_templates 等表...
create a mail queue subsystem which might include tables such as mail_queue, mail_status, mail_attachments, mail_recipients and mail_templates etc...
您可以考虑 PHPMailer
http://phpmailer.worxware.com/index.php?pg=exampleasendmail
您可以添加多个收件人和一个特殊的回调函数来处理每封发送的邮件的返回消息。 (例如,请访问链接)
我不认为可以通过 php 捕获“邮件发送失败”错误邮件,除非您通过 SMTP 使用 PHPMailer,并且偶尔观察来自任何收件人的任何返回消息您的外发电子邮件集合。
You might consider PHPMailer
http://phpmailer.worxware.com/index.php?pg=exampleasendmail
You can add multiple recipients and a special callback function for handling the returning messages for every single mail sent. (for an example visit the link)
I Don't think that catching a "mail delivery failed" error mail is possible via php except that you are using PHPMailer via SMTP and once in a while watch for any returning message form any recipient in from your outgoing email collection.