You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While trying to figure out how to replace c0d3.com's email system, I thought it would be nice to setup our own email servers for our students to use. This quickly threw me down a rabbit hole of how email servers work.
Setting up an email server is hard. When I started on this journey I didn't know what the keywords are to search for, making it difficult to find the content you need to understand how it works. If you simply looked up how to send emails, you will get pagefuls of tutorials telling you how to connect to gmail smtp, SES smtp, etc. Hard to find articles on how to setup your own server that sends emails, to run your own email delivery service.
This article is a documentation of the steps I took to run my own server that delivers my emails directly so I have a reference in case I need to set this up again in the future. Hopefully it helps someone out there.
This article should cover what is spf, dkim, and dmarc conceptually and how each of these are used as security measures to prevent spam.
This article also documents a few different tools that helped my debug and helped me make sure that my email server is configured correctly.
Steps
Below will be a list of steps that I took to set it up my own email server.
port 25?
Make sure Port 25 is turned on. Sending emails requires back and forth communication between servers on port 25. Because of spam, most hosting companies block port 25. Hostwinds (referral) is an example of a hosting company that allows port 25 by default (I tested this tutorial on their $5 server - Ubuntu 18.04).
After I ssh'd into server, I made sure to enable firewall on port 25: ufw allow 25
Setup and try
I used an application called sendmail to send email.
sudo apt install sendmail
With sendmail installed, I could have sent my first email! Tip: Do not send to a gmail or an email powered by google at this point. If you do this without your server configured correctly (covered in the later sections), your server's ip will be blacklisted and may take 2 weeks to remove after filling out this blacklist removal form.
Sample output of my ip adress being blocked by gmail. Notice the message Our system has detected an unusual rate of unsolicited mail originating from your IP address...
To make sure my sendmail application can deliver emails I used ethereal.email to generate emails on the fly and sent the account an email.
sendmail -v [email protected]
Subject: sample email subject here
email body goes here.
.
Make sure you exit out of the program by putting . on a new line an hitting enter. You should see messages output from the console. If you do not, you can find the logs in /var/log/mail.log.
I was able to verify that the email arrived in the email inbox and here's a sample output from my console:
Becoming Legit
Now that I can send a shitty email (that will probably get my server immediately blacklisted), it is time to make it legit.
Domain & Server
First I need a domain name. I got my domain name from godaddy. For the rest of the example I will be using my domain name m8l.me. I want my email server to be recognizable by domain name (smtp.m8l.me) so I added an A record for smtp.m8l.me to point to the ip address of our server.
(optional) - You should set your mx record to your subdomain for sending emails: smtp.m8l.me. When other servers (like gmail) need to deliver emails to your domain, they will look at this record to figure out where to send the email to. This tutorial does not show you how to receive emails, but setting up this record helps legitimize your domain.
Record
Host
points to
A
smtp
104.958.243.486
MX
smtp
smtp.m8l.me
Now when my server sends an email to gmail, gmail is going to do a reverse dns lookup to get domain name from the ip address of my server (Opposite from the usual dns lookup where it gets ip address from the domain name). To set this, I went to my hosting company where I got my server and configured the reverse DNS. Here is a direct link I used to configure my hostwind server reverse DNS record. I made sure both ipv4 and ipv6 ip addresses are configured with smtp.m8l.me.
To verify that reverse DNS is setup correctly, I ran dig -x 104.958.243.486 to see what domain name my ip address resolved to.
Now that my server is all mapped correctly to the domain, I need to make sure sendmail on my server identifies itself correctly when communicating with other email servers. Type hostname into the terminal on your server to see how it currently identifies itself. I want it to say smtp.m8l.me.
Here's what I did to set the hostname property on my server:
Set hostnamectl: sudo hostnamectl set-hostname smtp.m8l.me
Edit hostname file to reflect the new name: /etc/hostname
Restart: hostnamectl
Lastly, I deleted all the records and added smtp.m8l.me to this file: /etc/mail/local-host-names.
spf
When my server sends an email to gmail servers, they will first do a reverse dns lookup from my server's ip address to get the domain name. With this domain name gmail servers will look up my domain name's spf info to verify that my server has the permission to send email on behalf of that domain name.
To lookup a site's spf info (like gmail servers) you can look it up by fetching all the TXT records for the domain. To do this, run nslookup -q=TXT smtp.m8l.me in the terminal to get the TXT records for smtp.m8l.me.
To set my spf info, I needed to set my domain name's TXT record:
v=spf1 means version is spf1 spec. This specifies how to interpret the rest of the string.
ip:104... means that my email server (ip of 104...) has permission to send emails.
include:smtp.m8l.me means that smtp.m8l.me may be sending emails on my behalf (not 100% necessary for my case, but I put this anyways).
-all means the end of the string.
To verify that your TXT records are properly set, run nslookup -q=TXT smtp.m8l.me and look for the record that starts with v=spf1....
dkim
After verifying that my server has the permission to deliver email, gmail servers now needs to get my security information. It does this by looking at the dkim info for my domain name, which should specify the encryption that the email will use and the public key. In order to set this, I first need to generate a key.
To generate a public / private key, I needed to install opendkim and then mint the key (2 new files).
-b 1024 is important to make sure your dkim record is usable.
-s mail mail is going to be your Selector (important later when configuring dkim DNS info and opendkim encryption service).
-d smtp.m8l.me - the domain name for the key to be associated with.
I will get back 2 new files.
mail.txt specifies what how to set the dkim info for my domain name. Below is a sample output.
mail._domainkey IN TXT ("v1-DKIM1; h=sha256; k=rsa; p=M...DAQAB") ; -- DKIM key default for smtp.m8l.me
mail.private is a private key that sendmail will use to encrypt outgoing emails.
DNS - public key
Based on the content in mail.txt, I filled out my TXT record on my domain name provider like this:
host
TXT Value
mail._domainkey.smtp
v=DKIM1; h=sha256; k=rsa; p=MIG...DAQAB
For host, notice .smtp at the end. This is the subdomain of my domain name.
v=DKIM1; - specifies how to read the rest of the string
h=sha256 and k=rsa; specifies the encryption and the type of key.
p=MIG...DAQAB is your public key.
Your mail.txt record may have quotes. Make sure you don't have any quotes (") in your TXT value!
Remove mail.txt because we don't need it anymore: rm mail.txt
Encryption - private key
After gmail servers gets my public key from your dkim info of your domain name, they will now expect encrypted email from me. sendmail needs opendkim server to do all the encryption so I need to setup opendkim server and configure sendmail to encrypt emails with opendkim.
First I need to make sure I move my private key (mail.private) to the correct place.
Now I'm almost legit, there is one last step. Email servers like gmail will eventually get alot of requests that tries to pretend to be my domain. I need a DMARC info for my domain name so that gmail knows what to do when they receive these hostile emails that tries to impersonate my domain name.
To do this, I add a TXT record in my domain name's DNS records.
Now that I have the key components of an email configured, it is time to test it.
Debugging
To make sure opendkim is configured correctly, I tailed dkim logs:
sudo tail -f /var/log/syslog | grep -i dkim
To check if I had specified everything correctly, I searched for email deliverability test (this is a key word) that helps me verify my records. The easiest and did not require any signups is www.mail-tester.com. I sent an email to the provided address and got a 8.9/10 on my report!
Clicking on each section would tell you how what you configured incorrectly and why.
You con now use nodemailer and configure it to use sendmail as the transport layer. Sample code:
If you send with nodemailer, you should have a score of 10/10! The only thing that you can improve on at this point is to add a List-Unsubscribe header but that is only necessary when you send out regular newsletters.
Conclusion
All the work I did above is so that I can send emails to common email providers like gmail, outlook, yahoo, etc. without being blocked. Summary of the steps I took:
DNS
Configured TXT record for spf, dkim, dmarc.
Confired A and MX records
Server Provider
Got a server
Reverse DNS Record
Server
Configured hostname
Generate DKIM public / private key
Setup opendkim to use generated private key
Install and setup sendmail to use opendkim server
Troubleshoot
Getting errors when you run sudo apt install that looks like this? E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
This is because another apt process is running, perhaps an upgrade in the background. Run ps aux | grep -i apt to see what apt process are running.
The text was updated successfully, but these errors were encountered:
Intro
While trying to figure out how to replace c0d3.com's email system, I thought it would be nice to setup our own email servers for our students to use. This quickly threw me down a rabbit hole of how email servers work.
Setting up an email server is hard. When I started on this journey I didn't know what the keywords are to search for, making it difficult to find the content you need to understand how it works. If you simply looked up
how to send emails
, you will get pagefuls of tutorials telling you how to connect togmail smtp
,SES smtp
, etc. Hard to find articles on how to setup your own server that sends emails, to run your own email delivery service.This article is a documentation of the steps I took to run my own server that delivers my emails directly so I have a reference in case I need to set this up again in the future. Hopefully it helps someone out there.
This article should cover what is spf, dkim, and dmarc conceptually and how each of these are used as security measures to prevent spam.
This article also documents a few different tools that helped my debug and helped me make sure that my email server is configured correctly.
Steps
Below will be a list of steps that I took to set it up my own email server.
port 25?
Make sure Port 25 is turned on. Sending emails requires back and forth communication between servers on port 25. Because of spam, most hosting companies block port 25. Hostwinds (referral) is an example of a hosting company that allows port 25 by default (I tested this tutorial on their $5 server - Ubuntu 18.04).
After I ssh'd into server, I made sure to enable firewall on port 25:
ufw allow 25
Setup and try
I used an application called
sendmail
to send email.With sendmail installed, I could have sent my first email! Tip: Do not send to a gmail or an email powered by google at this point. If you do this without your server configured correctly (covered in the later sections), your server's ip will be blacklisted and may take 2 weeks to remove after filling out this blacklist removal form.
Sample output of my ip adress being blocked by gmail. Notice the message
Our system has detected an unusual rate of unsolicited mail originating from your IP address
...To make sure my sendmail application can deliver emails I used ethereal.email to generate emails on the fly and sent the account an email.
Make sure you exit out of the program by putting
.
on a new line an hitting enter. You should see messages output from the console. If you do not, you can find the logs in/var/log/mail.log
.I was able to verify that the email arrived in the email inbox and here's a sample output from my console:
Becoming Legit
Now that I can send a shitty email (that will probably get my server immediately blacklisted), it is time to make it legit.
Domain & Server
First I need a domain name. I got my domain name from godaddy. For the rest of the example I will be using my domain name
m8l.me
. I want my email server to be recognizable by domain name (smtp.m8l.me
) so I added anA
record forsmtp.m8l.me
to point to the ip address of our server.(optional) - You should set your
mx
record to your subdomain for sending emails:smtp.m8l.me
. When other servers (like gmail) need to deliver emails to your domain, they will look at this record to figure out where to send the email to. This tutorial does not show you how to receive emails, but setting up this record helps legitimize your domain.Now when my server sends an email to gmail, gmail is going to do a
reverse dns
lookup to get domain name from the ip address of my server (Opposite from the usual dns lookup where it gets ip address from the domain name). To set this, I went to my hosting company where I got my server and configured the reverse DNS. Here is a direct link I used to configure my hostwind server reverse DNS record. I made sure bothipv4
andipv6
ip addresses are configured withsmtp.m8l.me
.To verify that reverse DNS is setup correctly, I ran
dig -x 104.958.243.486
to see what domain name my ip address resolved to.Now that my server is all mapped correctly to the domain, I need to make sure
sendmail
on my server identifies itself correctly when communicating with other email servers. Typehostname
into the terminal on your server to see how it currently identifies itself. I want it to saysmtp.m8l.me
.Here's what I did to set the
hostname
property on my server:hostnamectl
:sudo hostnamectl set-hostname smtp.m8l.me
/etc/hostname
hostnamectl
Lastly, I deleted all the records and added
smtp.m8l.me
to this file:/etc/mail/local-host-names
.spf
When my server sends an email to gmail servers, they will first do a reverse dns lookup from my server's ip address to get the domain name. With this domain name gmail servers will look up my domain name's
spf
info to verify that my server has the permission to send email on behalf of that domain name.To lookup a site's
spf
info (like gmail servers) you can look it up by fetching all the TXT records for the domain. To do this, runnslookup -q=TXT smtp.m8l.me
in the terminal to get the TXT records forsmtp.m8l.me
.To set my
spf
info, I needed to set my domain name'sTXT
record:In the above record:
v=spf1
means version isspf1
spec. This specifies how to interpret the rest of the string.ip:104...
means that my email server (ip of 104...) has permission to send emails.include:smtp.m8l.me
means thatsmtp.m8l.me
may be sending emails on my behalf (not 100% necessary for my case, but I put this anyways).-all
means the end of the string.To verify that your
TXT
records are properly set, runnslookup -q=TXT smtp.m8l.me
and look for the record that starts withv=spf1...
.dkim
After verifying that my server has the permission to deliver email, gmail servers now needs to get my security information. It does this by looking at the
dkim
info for my domain name, which should specify the encryption that the email will use and the public key. In order to set this, I first need to generate a key.To generate a public / private key, I needed to install
opendkim
and then mint the key (2 new files).-b 1024
is important to make sure your dkim record is usable.-s mail
mail is going to be yourSelector
(important later when configuringdkim
DNS info and opendkim encryption service).-d smtp.m8l.me
- the domain name for the key to be associated with.I will get back 2 new files.
mail.txt specifies what how to set the
dkim
info for my domain name. Below is a sample output.mail.private is a private key that sendmail will use to encrypt outgoing emails.
DNS - public key
Based on the content in
mail.txt
, I filled out myTXT
record on my domain name provider like this:host
, notice.smtp
at the end. This is the subdomain of my domain name.v=DKIM1;
- specifies how to read the rest of the stringh=sha256
andk=rsa;
specifies the encryption and the type of key.p=MIG...DAQAB
is your public key.mail.txt
record may have quotes. Make sure you don't have any quotes ("
) in yourTXT
value!Remove
mail.txt
because we don't need it anymore:rm mail.txt
Encryption - private key
After gmail servers gets my public key from your
dkim
info of your domain name, they will now expect encrypted email from me.sendmail
needsopendkim
server to do all the encryption so I need to setupopendkim
server and configure sendmail to encrypt emails withopendkim
.First I need to make sure I move my private key (
mail.private
) to the correct place.Now I want to configure
opendkim
service to encrypt with the correct key and specify the correct domain.vim /etc/opendkim.conf
mail
is the Selector I used to generate the original key.In the same file, I need to specify the socket to run on the correct port.
Make sure all other instances of
Socket
are commented out.Now edit another
opendkim
config file:vim /etc/default/opendkim
Start/Restart
opendkim
service:sudo systemctl restart opendkim
orsudo systemctl start opendkim
.To make sure my server is running on the correct specified port (
8891
), I ranlsof -i:8891
to check.Lastly, I needed to configure
sendmail
to use this opendkim service to encrypt emails.Sendmail
Append the following into
/etc/mail/sendmail.mc
Regenerate
sendmail
config file as root:Restart sendmail
DMARC
Now I'm almost legit, there is one last step. Email servers like gmail will eventually get alot of requests that tries to pretend to be my domain. I need a
DMARC
info for my domain name so that gmail knows what to do when they receive these hostile emails that tries to impersonate my domain name.To do this, I add a
TXT
record in my domain name's DNS records._dmarc.smtp
- Careful, make sure you put in the_dmarc
subdomain prefix in front of your subdomain.v=DMARC1;
- specifies how to read the rest of the stringp=reject;pct=100
- Reject 100% of all emails that are trying to impersonate my domain name.mailto:[email protected]
- Send aggregated reports of how many emails were rejected to[email protected]
Now that I have the key components of an email configured, it is time to test it.
Debugging
To make sure
opendkim
is configured correctly, I taileddkim
logs:To check if I had specified everything correctly, I searched for
email deliverability test
(this is a key word) that helps me verify my records. The easiest and did not require any signups is www.mail-tester.com. I sent an email to the provided address and got a8.9/10
on my report!Clicking on each section would tell you how what you configured incorrectly and why.
You con now use nodemailer and configure it to use
sendmail
as the transport layer. Sample code:If you send with nodemailer, you should have a score of 10/10! The only thing that you can improve on at this point is to add a
List-Unsubscribe header
but that is only necessary when you send out regular newsletters.Conclusion
All the work I did above is so that I can send emails to common email providers like gmail, outlook, yahoo, etc. without being blocked. Summary of the steps I took:
DNS
TXT
record forspf
,dkim
,dmarc
.A
andMX
recordsServer Provider
Server
opendkim
to use generated private keysendmail
to useopendkim
serverTroubleshoot
sudo apt install
that looks like this?E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
apt
process is running, perhaps an upgrade in the background. Runps aux | grep -i apt
to see whatapt
process are running.The text was updated successfully, but these errors were encountered: