Send something by email

There are two spells for doing a website in China. The first one is that the registered emails are not received.

Why do you do it yourself

There are two magic spells for making a website in China that you can't escape.

The first is that registered emails are always not received by users; the other is that DDOS is immediately famous.

In order to avoid the first curse, we bought the paid users of SendCloud early.

Every day, dozens to hundreds of registered users think they are very reliable. Until the homepage was revised, we put a customer service phone on the prompt information page sent by email.

Then every three to five, there was a customer phone complaint saying that the activation email was not reached. We were very depressed. We used the "best Eastern Hemisphere" mail service provider.

Later, I couldn't bear to resend the emails by hand every day. Luo Fei said, let's use WebHook to make a rebound. Once the delivery is unsuccessful, we will automatically send an email to our operations staff.

As a result, we found that some successfully sent emails were also returned by Hook. Then Luo Fei collapsed T__T.

In fact, I'm not here to vomit, SendCloud is still the first choice of domestic mail service providers, after all, this is the only one.

Last weekend, I carefully analyzed the next problem and tried to make a solution, write it out and share it with everyone.

demand

First of all, our needs are somewhat special. Job seekers do not need to register in JobDeer, upload resumes directly, and the consultant opens an account; while recruiters, we require that you must use company mailboxes, and public mailboxes like QQ are not allowed.

Many companies' corporate mailboxes have IP anti-spam enabled, and many spam spam emails are sent using SendCloud and Mailgun-they share IP by default, so they quickly entered the IP blacklist.

Most of SendCloud's customers send letters to public mailboxes, so just ask QQ, Gmail, and 163 to add themselves to the whitelist. But this is not necessarily the case with corporate mailboxes.

This is why we believe that the common IP-sharing platform for sharing IP is not effective. Not necessarily right, just our thinking.

solution

So how to solve it? Change the independent IP.

sendcloud

SendCloud's independent IP is too expensive to hurt. It is said that because the public IP resources on hand are limited, they can only limit the price. As a student who has done cloud, I express my understanding, but I still can't afford it after understanding.

So I went to see the price of Mailgun-$ 59 per month, which was barely acceptable. But given our small volume of mail, we always feel uncomfortable.

Finally, I decided to build an MTA myself, which is a mail transfer server. The reasons are as follows:

  • The corporate mailbox should not add a blacklist to the new domain name and IP. We send registration and subscription emails with regular content, so the blacklist rule will not be triggered.
  • Our overall sending volume is in the thousands of levels per day, this amount will not trigger the ban on public mailboxes
  • We have several VPSs with public IPs in Meituan Cloud, just build them directly without buying additional IPs.

Build Postfix

As a former PHP programmer with a fear of operating system maintenance, I generally use Ubuntu. Installing Postfix on Ubuntu is very easy.

After apt-get install, a character interface can be selected and set. I chose Internet with SmartHost.

The specific installation process can refer to here:  https://www.digitalocean.com/community/tutorials/how-to-install-and-setup-postfix-on-ubuntu-14-04

It should be noted that Postfix is ​​only open to the client of the local IP by default, because we use PHP to call Postfix to send, so there is no modification.

Configure PHP

In php.ini, modify sendmail_path to / usr / sbin / sendmail -t -i so that PHP's Mail function can send normal mail.

Sending directly with the Mail function will be a little trouble, in addition to encoding, it will write from as [email protected]. I didn't find anything to change, so I sent it directly with PHPMailer.

$mail = $GLOBALS['LP_MAILER'];
$mail->CharSet = 'UTF-8';
$mail->Encoding = 'base64';
$mail->MessageID = $mid . '@'.c('mail_domain');

$mail->SetFrom( c('mail_from') );
$mail->AddReplyTo( c('mail_from') );

$mail->Subject = $subject ;
$mail->WordWrap = 50;
$mail->MsgHTML($body);
$mail->AddAddress( $to );

if(!$mail->Send())
{
    $GLOBALS['LP_MAILER_ERROR'] = $mail->ErrorInfo;
    return false;
}
else
{
    $mail->ClearAddresses();
    return true;
}

When sending in PHPMailer, you can specify from at will, but don't be happy, when from is different from the actual sending user, mail will be marked as spam in many systems.

At the same time, sending emails is a time-consuming operation and should not allow web processes to wait for a long time. Otherwise, a little bit of concurrent servers will hang. How to do? Do real-time queues.

Redis queue

Don't use cron for queues, dirt. In fact, Redis provides a Pub / Sub service that blocks reading from a certain version. This thing is very useful for real-time queues. To make this queue better, it is strongly recommended to install the phpredis pecl extension.

The logic of Pub / Sub service is simple. Use the command line to start a PHP, subscribe to a Channel, this PHP has been waiting. As long as the Web program uses Redis to publish the data into the same Channel, the command line PHP will get the data and trigger the callback function.

On the code, subscribers:

ini_set('default_socket_timeout', -1);

$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$channelname = c('mail_channel'); 
try
{
    $redis->subscribe(array($channelname), 'mailsend');
}catch(Exception $e)
{
echo $e->getMessage();
}

By the way, the default_socket_timeout, if you want to use PHP to connect to the socket for a long time, you must set this value, otherwise it will break.

The code above will keep this PHP running all the time and will not end. That's why I recommend the pecl extension. You don't need to write while, it will process it by itself, and when there is data, it will call back the mailsend function.

function mailsend($instance, $channelName, $message) 

The mailsend function can obtain the above parameters, of which $ message is the most important. Generally, after serializing the array, pass it through publish. Below is the publisher's code:

$redis = new Redis();
$redis->connect('127.0.0.1',6379);

$info = array();
$info['to'] = $to;
$info['subject'] = $subject;
$info['content'] = $content;

if($ret = $redis->publish( c('mail_channel') , serialize($info) ))
{
return send_result( 'send to ' . $to . ' add to queue' );
}
else 
    return send_error( $ret );

It's very simple and very convenient to use.

As mentioned above, because the user calling the mail function is www-data, the real mail box is [email protected], and you want to display as [email protected]. To ensure consistency is very simple, just use easy users to start the subscriber PHP.

su easy
nohup php sub.php & 

Further adapt anti-spam rules

In order to prevent others from using your email address to send letters to public mailboxes, you can enable SPF and DKIM.

If you just send a letter, SPF does not need to install anything, just add a TXT record to the DNS of the sending domain name. The format is probably like this:

v=spf1 ip4:106.3.32.60 ~all 

This sentence tells the receiving server that if the mailbox under this domain name is not sent from 106.3.32.60, it is directly marked as spam.

DKIM is relatively complicated. It will sign the content of the email, and then the receiving server obtains the public key through DNS, and checks whether the signature is correct.

The specific operation is to add a content filter to Postfix. For detailed instructions, please refer here: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy

After all this is done, it will be difficult for others to stolen the spam you have sent yourself. As long as you clean yourself, you can pass anti-spam rules smoothly.

Content Anti-Spam

During the test, I found that my test mailbox went into the trash box of Gmail. One of the advantages of Gmail is that it will indicate why mail will go into the trash box. This is useful for us to adjust the content of the email. Generally speaking, it is more reliable to write the complete content in the text as much as possible than the optical hair attachment. There are also some advertising words commonly used in spam, which should be avoided.

Further thinking

After completing the function of Postfix self-mailing, Luo Fei and I discussed the unreliability of cloud services. We feel that cloud services should be regarded as unreliable. There will always be times when it fails, including services that we build ourselves.

How to build a reliable business support on an unreliable cloud? Go single. Yes, the cloud should also be viewed as a single point. If we overlap the same type of cloud services, when the first layer service is down and the second layer service is automatically enabled, the possibility of affecting the business due to cloud instability will be greatly reduced.

Because 0.1% * 0.1% = 0.0001%, the possibility of two services failing at the same time is greatly reduced.

Under this line of thought, we made the "Nine Tail Cat." It provides a mechanism to ensure that the standby service provider will be automatically activated after the main service provider hangs up. As with the cat's nine lives, as long as the service provider does not hang up, the business itself will not hang up.

Nine-tailed cat has several core concepts

  • Service: Cloud service, now only mail
  • Method: Service providers, there are two layers of Mailgun and Postfix, and will send SendCloud in the future (wait for them to fix Hook and buy a semi-independent IP to try their luck), Sina mail service (yes, Sina has also done it, is on a small scale) Test) and SMTP access come in.
  • Level: Priority, each Method is assigned a priority. When level1 is hung, it will automatically find level2 for processing and accumulate in turn, up to level9. The level of each service provider can be adjusted according to service quality.

The Nine-Tailed Cat is a small attempt of ours, which mainly serves internally, and is mainly written to share ideas with you. With this idea, reliable cloud can be encapsulated in unreliable services such as SMS sending and resume analysis. We will slowly optimize it and consider providing external services when appropriate.

Published 57 original articles · praised 0 · visits 2169

Guess you like

Origin blog.csdn.net/zhidc/article/details/105333650