User Tools

Site Tools


computing:mailserver

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
computing:mailserver [2025/04/08 13:18] oemb1905computing:mailserver [2025/04/23 20:55] (current) oemb1905
Line 11: Line 11:
 ------------------------------------------- -------------------------------------------
  
-This tutorial is for users of Debian GNU/Linux who want to set up a proper email server.. This tutorial assumes you know how to set up A, AAAA, SPF, DKIM, DMARC, MX, and PTR records. Set an A record for example.org and mail.example.org. If you don't know how, then learn up, and do not proceed. //Thanks to LinuxBabe for a great jumping off point//.+This tutorial is for users of Debian GNU/Linux who want to set up a proper email server.. This tutorial assumes you know how to set up A, AAAA, SPF, DKIM, DMARC, MX, and PTR records. Set an A record for example.org and mail.example.org. If you don't know how, then learn up, and do not proceed. //Thanks to LinuxBabe for a great jumping off point//Let's begin by editing our hosts file ''sudo nano /etc/hosts'' as follows:
  
-  sudo nano /etc/hosts+  127.0.1.1 example.org example 
 +  127.0.0.1 mail.example.org localhost
  
-Edit the second line and add a line to the bottom similar to: +Install postfix and mailutils ''sudo apt-get install mailutils postfix -y'' picking ''Internet Site'' and set your domain to ''example.org''.
- +
-  <127.0.1.1 example.org example> +
-  <127.0.0.1 mail.example.org localhost> +
- +
-Install postfix and mailutils +
- +
-  sudo apt-get install mailutils postfix -y +
-  <Internet Site+
-  <example.org>+
  
 Install firewall, open common ports for front facing website, and for imap/smtp: Install firewall, open common ports for front facing website, and for imap/smtp:
Line 30: Line 22:
   sudo apt install ufw   sudo apt install ufw
   sudo ufw allow 22/tcp   sudo ufw allow 22/tcp
-  sudo ufw allow 53/tcp 
   sudo ufw allow 25/tcp   sudo ufw allow 25/tcp
   sudo ufw allow 587/tcp   sudo ufw allow 587/tcp
   sudo ufw allow 143/tcp   sudo ufw allow 143/tcp
 +  sudo ufw allow 465/tcp
   sudo ufw allow 993/tcp   sudo ufw allow 993/tcp
   sudo ufw allow 80   sudo ufw allow 80
Line 42: Line 34:
   sudo postconf -e message_size_limit=52428800   sudo postconf -e message_size_limit=52428800
  
-Set hostname and aliases +Set hostname and aliases in ''sudo nano /etc/postfix/main.cf'' and make sure that the hostname, origin, destination, mailbox size, and quota are set. Also, in my case, I only have ipv4 support, so I explicitly set that as well.
- +
-  sudo nano /etc/postfix/main.cf +
-   +
-Make sure that the hostname, origin, destination, mailbox size, and quota are set. Also, in my case, I only have ipv4 support, so I explicitly sett that as well.+
      
   myhostname = mail.example.com   myhostname = mail.example.com
Line 129: Line 117:
   smtpd_sasl_security_options = noanonymous   smtpd_sasl_security_options = noanonymous
  
-Now, we can install dovecot and configure it to use IMAP, change the default mailbox location, and add dovecot to the mail group:+Now, we can install dovecot and configure it to use IMAP and lmtp. Install the packages with ''sudo apt install dovecot-core dovecot-imapd dovecot-lmtpd'' and then edit ''sudo nano /etc/dovecot/dovecot.conf'': 
 + 
 +  <protocols = imap lmtp> 
 + 
 +After that, open ''sudo nano /etc/dovecot/conf.d/10-mail.conf'' and change the default mail director location as follows:
  
-  sudo apt install dovecot-core dovecot-imapd 
-  sudo nano /etc/dovecot/dovecot.conf 
-  <protocols = imap> 
-  sudo nano /etc/dovecot/conf.d/10-mail.conf 
   <mail_location = maildir:~/Maildir>   <mail_location = maildir:~/Maildir>
-  sudo adduser dovecot mail 
-   
-We will now configure dovecot to use lmtp and in so doing use spam sieve and other modules: 
  
-  sudo apt install dovecot-lmtpd +Let's make sure dovecot is part of the mail group, including any users you intend to use email:
-  sudo nano /etc/dovecot/dovecot.conf +
-  <protocols = imap lmtp>+
  
-Nowwe need to edit ''sudo nano /etc/dovecot/conf.d/10-master.conf'' and make sure that dovecot can leverage lmtp:+  sudo adduser dovecot mail 
 +  sudo adduser username mail 
 +   
 +Now we can configure dovecot over at ''sudo nano /etc/dovecot/conf.d/10-master.conf'' in order to be able to leverage lmtp:
  
   service lmtp {   service lmtp {
Line 154: Line 140:
    }    }
  
-Similarly, we need to edit postfix for lmtp:+Similarly, we need to edit postfix for lmtp as well with ''sudo nano /etc/postfix/main.cf'' and then specifying:
  
-  sudo nano /etc/postfix/main.cf +  mailbox_transport = lmtp:unix:private/dovecot-lmtp 
-  <mailbox_transport = lmtp:unix:private/dovecot-lmtp> +  smtputf8_enable = no
-  <smtputf8_enable = no>+
  
-Next, let's configure dovecot authorization:+Next, let's configure dovecot authorization with ''sudo nano /etc/dovecot/conf.d/10-auth.conf'' plain login as follows:
  
-  sudo nano /etc/dovecot/conf.d/10-auth.conf +  disable_plaintext_auth = yes 
-  <disable_plaintext_auth = yes> +  auth_username_format = %n 
-  <auth_username_format = %n> +  auth_mechanisms = plain login
-  <auth_mechanisms = plain login>+
      
-Now, configure SSL/TLS encryption in dovecot:+Now, configure SSL/TLS encryption in dovecot using your website/domain certs from earlier with ''sudo nano /etc/dovecot/conf.d/10-ssl.conf'':
  
-  sudo nano /etc/dovecot/conf.d/10-ssl.conf +  ssl = required 
-  <ssl = required> +  ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem 
-  <ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem> +  ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem 
-  <ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem> +  ssl_prefer_server_ciphers = yes 
-  <ssl_prefer_server_ciphers = yes> +  ssl_min_protocol = TLSv1.2
-  <ssl_min_protocol = TLSv1.2>+
      
-SASL configuration by editing ''sudo nano /etc/dovecot/conf.d/10-master.conf'' and adding this block:+Set up the SASL listener by editing ''sudo nano /etc/dovecot/conf.d/10-master.conf'' and adding this block:
  
   service auth {   service auth {
Line 191: Line 174:
   openssl s_client -starttls smtp -connect mail.example.com:25   openssl s_client -starttls smtp -connect mail.example.com:25
      
-Now it is time to setup an spf policy agent so that the incoming email that is received checks for validity of spf records. **Do not confuse this with creating an spf TXT record for your outgoing email.**+Now it is time to setup an spf policy agent so that the incoming email that is received checks for validity of spf records. **Do not confuse this with creating an spf TXT record for your outgoing email.** Let's install spf policy with ''sudo apt install postfix-policyd-spf-python''and then edit ''sudo nano /etc/postfix/master.cf'' as follows: 
 +   
 +  policyd-spf  unix  -                               spawn 
 +  user=policyd-spf argv=/usr/bin/policyd-spf 
 +   
 +After that, let's set up ''sudo nano /etc/postfix/main.cf'' as follows:
  
-  sudo apt install postfix-policyd-spf-python +  policyd-spf_time_limit = 3600 
-  sudo nano /etc/postfix/master.cf +  smtpd_recipient_restrictions = 
-  <policyd-spf  unix  -                               spawn> +   permit_mynetworks, 
-  <user=policyd-spf argv=/usr/bin/policyd-spf> +   permit_sasl_authenticated, 
-  sudo nano /etc/postfix/main.cf +   reject_unauth_destination, 
-  <policyd-spf_time_limit = 3600> +   check_policy_service unix:private/policyd-spf
-  <smtpd_recipient_restrictions => +
-   <permit_mynetworks,> +
-   <permit_sasl_authenticated,> +
-   <reject_unauth_destination,> +
-   <check_policy_service unix:private/policyd-spf>+
  
-Now, it is time to set up DKIM on your server. After creating the DKIM record/key on your server, you will need to create a corresponding TXT record for it to establish that anything over smtp with that signature is, in fact, you/your server.+Now, it is time to set up DKIM on your server. After creating the DKIM record/key on your server, you will need to create a corresponding TXT record for it to establish that anything over smtp with that signature is, in fact, you/your server. Let's install opendkim with ''sudo apt install opendkim opendkim-tools'' and add postfix to its group with ''sudo adduser postfix opendkim'' and then adjust the configuration in ''sudo nano /etc/opendkim.conf'' as follows:
  
-  sudo apt install opendkim opendkim-tools +  Canonicalization   relaxed/simple 
-  sudo adduser postfix opendkim +  Mode               sv 
-  sudo nano /etc/opendkim.conf +  SubDomains         no 
-  <Canonicalization   relaxed/simple> +  Nameservers     8.8.8.8,1.1.1.1 
-  <Mode               sv> +  KeyTable           refile:/etc/opendkim/key.table 
-  <SubDomains         no> +  SigningTable       refile:/etc/opendkim/signing.table 
-  <Nameservers     8.8.8.8,1.1.1.1> +  ExternalIgnoreList  /etc/opendkim/trusted.hosts 
-  <KeyTable           refile:/etc/opendkim/key.table> +  InternalHosts       /etc/opendkim/trusted.hosts
-  <SigningTable       refile:/etc/opendkim/signing.table> +
-  <ExternalIgnoreList  /etc/opendkim/trusted.hosts> +
-  <InternalHosts       /etc/opendkim/trusted.hosts>+
  
 Now that the configuration for DKIM is ready, let's create the keys and content for the locations specified above: Now that the configuration for DKIM is ready, let's create the keys and content for the locations specified above:
Line 224: Line 204:
   sudo chown -R opendkim:opendkim /etc/opendkim   sudo chown -R opendkim:opendkim /etc/opendkim
   sudo chmod 711 /etc/opendkim/keys   sudo chmod 711 /etc/opendkim/keys
-  sudo nano /etc/opendkim/signing.table +   
-  <*@example.com      default._domainkey.example.com> +Once all the directories and key locations are created, let's open the signing table with ''sudo nano /etc/opendkim/signing.table'' and enter the following (without the single quotes required here due to markdown conflict): 
-  <*@*.example.com    default._domainkey.example.com> + 
-  sudo nano /etc/opendkim/key.table +  '*@example.com      default._domainkey.example.com' 
-  <default._domainkey.example.com     example.com:default:/etc/opendkim/keys/example.com/default.private> +  '*@*.example.com    default._domainkey.example.com' 
-  sudo nano /etc/opendkim/trusted.hosts + 
-  <.domain.com>+Now that the signing table is setup, we need to edit the key table with ''sudo nano /etc/opendkim/key.table'' and enter the following: 
 + 
 +  default._domainkey.example.com     example.com:default:/etc/opendkim/keys/example.com/default.private 
 + 
 +The trusted hosts is next, over in ''sudo nano /etc/opendkim/trusted.hosts'' which we simply enter: 
 + 
 +  127.0.0.1 
 +  localhost 
 +  .domain.com 
 +   
 +We now need to cut the DKIM keys (and make sure to add TXT records on your DNS host later) as follows: 
 +  
   sudo mkdir /etc/opendkim/keys/example.com   sudo mkdir /etc/opendkim/keys/example.com
   sudo opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s default -v   sudo opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s default -v
Line 236: Line 227:
   sudo chmod 600 /etc/opendkim/keys/example.com/default.private   sudo chmod 600 /etc/opendkim/keys/example.com/default.private
  
-It's now time to create the corresponding TXT record for this DKIM key. To do that, display the key with ''sudo cat /etc/opendkim/keys/example.com/default.txt'' and then copy everything between the parentheses into your TXT record with ''default._domainkey'' as the host. After the DKIM TXT record caches, test it as follows:+To get the information you need for the DNS record, you can run ''sudo cat /etc/opendkim/keys/example.com/default.txt'' and then copy everything between the parentheses into your TXT record with ''default._domainkey'' as the host. After the DKIM TXT record caches, test it as follows:
  
   sudo opendkim-testkey -d example.com -s default -vvv   sudo opendkim-testkey -d example.com -s default -vvv
      
-Note that that output will display "key not secure" unless you configure DNSSEC, which this tutorial has not done. It's now time to configure postfix to leverage this DKIM key.+Note that that output will display "key not secure" unless you configure DNSSEC, which this tutorial has not done. It's now time to configure postfix to leverage this DKIM key. Let's make a directory for the socket and set up the configuration:
  
   sudo mkdir /var/spool/postfix/opendkim   sudo mkdir /var/spool/postfix/opendkim
   sudo chown opendkim:postfix /var/spool/postfix/opendkim   sudo chown opendkim:postfix /var/spool/postfix/opendkim
   sudo nano /etc/opendkim.conf   sudo nano /etc/opendkim.conf
-  <Socket    local:/var/spool/postfix/opendkim/opendkim.sock> +   
-  sudo nano /etc/default/opendkim +In the dkim config file, enter
-  <SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"> +   
-  sudo nano /etc/postfix/main.cf +  Socket    local:/var/spool/postfix/opendkim/opendkim.sock 
-  <milter_default_action = accept> +   
-  <milter_protocol = 6> +After establishing the socket directory and location, let's configure our dkim defaults in ''sudo nano /etc/default/opendkim'' and editing:
-  <smtpd_milters = local:opendkim/opendkim.sock> +
-  <non_smtpd_milters = $smtpd_milters>+
  
-It's now a good time to test your email quality with [[https://mail-tester.com|Mail Tester]] to see if you got a 10/10 score. When upgrading postfix on the server, select "No configuration" as otherwise it will overwrite the configurations above. If you need help with creating spf, dmarc, or dkim TXT records, see [[https://wiki.haacksnetworking.org/doku.php?id=computing:spfdkim|spfdkim]]. Another optional setting is to reject incoming email that lacks a PTR (reverse DNS) record+  SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
  
-  sudo nano /etc/postfix/main.cf +Lastly, we need to configure postfix to be able to use opendkim in ''sudo nano /etc/postfix/main.cf'' by editing: 
-  <smtpd_sender_restrictions => + 
-      <permit_mynetworks,> +  milter_default_action accept 
-      <permit_sasl_authenticated,> +  milter_protocol = 6 
-      <reject_unknown_reverse_client_hostname,> +  smtpd_milters = local:opendkim/opendkim.sock 
-      <reject_unknown_client_hostname,> +  non_smtpd_milters = $smtpd_milters 
-      <reject_unknown_sender_domain,+ 
-      <reject_unauthenticated_sender_login_mismatch,> +In addition to spf and dkim policiesit's also best practice to have a dmarc policy. Let's install opendmarc with ''sudo apt install opendmarc'' and make sure to say no to db configure in the ncurses prompt, after which you should open ''sudo nano /etc/opendmarc.conf'' and enter something like:
-      <reject_sender_login_mismatch> +
-      <permit> +
-     +
-To set up email header and/or body checks to prevent spam:+
  
-  sudo apt install postfix-pcre +  AuthservID OpenDMARC 
-  sudo nano /etc/postfix/main.cf +  TrustedAuthservIDs mail.yourdomain.com 
-  <header_checks = pcre:/etc/postfix/header_checks> +  RejectFailures true 
-  <body_checks = pcre:/etc/postfix/body_checks>+  IgnoreAuthenticatedClients true 
 +  RequireHeaders true 
 +  SPFSelfValidate true 
 +  Socket local:/var/spool/postfix/opendmarc/opendmarc.sock
      
-You will then need to configure the files with whatever strings you expect spam headers or bodies to haveand either reject them and/or discard them. You will also need to rebuild the indexesYou may optionally set up dmarc verification and reporting with openDMARC.+The opendmarc socket also needs its directory createdsimilar to dkimSo let's create a directory for it ''sudo mkdir -p /var/spool/postfix/opendmarc'' and then set permissions and restart the service:
  
-  sudo apt install opendmarc 
-  <no to db configure> 
-  sudo nano /etc/opendmarc.conf 
-  <AuthservID OpenDMARC> 
-  <TrustedAuthservIDs mail.yourdomain.com> 
-  <RejectFailures true> 
-  <IgnoreAuthenticatedClients true> 
-  <SPFSelfValidate true> 
-  <Socket local:/var/spool/postfix/opendmarc/opendmarc.sock> 
-  sudo mkdir -p /var/spool/postfix/opendmarc 
   sudo chown opendmarc:opendmarc /var/spool/postfix/opendmarc -R   sudo chown opendmarc:opendmarc /var/spool/postfix/opendmarc -R
   sudo chmod 750 /var/spool/postfix/opendmarc/ -R   sudo chmod 750 /var/spool/postfix/opendmarc/ -R
Line 291: Line 269:
   sudo systemctl restart opendmarc   sudo systemctl restart opendmarc
      
-Now, configure postfix to work with openDMARC. Add the openDMARC socket to the milter block you created earlier.+Now, we need to configure postfix to work with openDMARC. Expand the milter to include openDMARC'socket by opening ''sudo nano /etc/postfix/main.cf'' and adjusting the following block:
  
-  sudo nano /etc/postfix/main.cf +  milter_default_action = accept 
-  <milter_default_action = accept> +  milter_protocol = 6 
-  <milter_protocol = 6> +  smtpd_milters = local:opendkim/opendkim.sock,local:opendmarc/opendmarc.sock 
-  <smtpd_milters = local:opendkim/opendkim.sock,local:opendmarc/opendmarc.sock> +  non_smtpd_milters = $smtpd_milters
-  <non_smtpd_milters = $smtpd_milters+
-  sudo systemctl restart postfix +
-   +
-This about covers everything. The only missing part is how to get past picky microsoft users and/or automate or simplify account creation. Okay, to view and/or delete messages from postfix mailq:+
  
-  mailq +It'about time to setup spam controlsbut before we do that, we need to make sure mission critical IMAP folders populate on clientsLet'open ''sudo nano /etc/dovecot/conf.d/15-mailboxes.conf'' and enter the auto-create line on folders that you need:
-  postcat -q E900C4780073 +
-  postsuper -d E900C4780073 +
-  postsuper -d ALL +
-   +
-If you have issues, it'good to be familiar with some different uses of the ''dig'' command to test your records. Here's how to check dmarc, dkim, spf, and ptr. The ''+short'' is optional, of course. I also included how you can verify your dkim key as well. +
-   +
-  dig txt +short _dmarc.jonathanhaack.com +
-  dig txt +short _dmarc.haacksnetworking.org +
-  dig default._domainkey.jonathanhaack.com txt +
-  dig default._domainkey.haacksnetworking.org txt +
-  dig txt +short jonathanhaack.com +
-  dig txt +short haacksnetworking.org +
-  dig -x 8.28.86.130 +short +
-  dig -x 8.28.86.125 +short +
-  sudo opendkim-testkey -d jonathanhaack.com -s default -vvv +
-  sudo opendkim-testkey -d haacksnetworking.org -s default -vvv +
-   +
-Alsoplease note that the above applies to clients connecting to the domain. If you intend to also host websites/content on the same host as the mail serverthen you will also need to set up dmarc, spf, and mx records for the subdomain, mail.example.com. You will not need to setup dkim nor change the PTR. To test the validity of the command line email set up, ssh into your server and send an email as follows: +
- +
-  echo "Hi, I am testing the subdomain email health." | mail -s "CLI Email Test" oemb1905@jonathanhaack.com +
- +
-It'also common to ''auto = create'' mission-critical folders in IMAP. +
- +
-  sudo nano /etc/dovecot/conf.d/15-mailboxes.conf +
- +
-An example block:+
  
   mailbox Drafts {   mailbox Drafts {
-    auto = create+    **auto = create**
     special_use = \Drafts     special_use = \Drafts
   }   }
  
-Simply add the ''auto = create'' to whichever directories you need. Some smtp servers and/or MTAs capitalize the user name of your email without permissionTo avoid having your server reject these, please add the following to `main.cf.`+Since I use lmtp, which is case-sensitive, and sends incoming mail to dovecot, which is also case-sensitive, I created virtual aliases in order to avoid emails being rejected when auto-mailers capitalize or otherwise punctuate the email user name. Let's open ''sudo nano /etc/postfix/main.cf'' and add another block:
  
   virtual_alias_maps = regexp:/etc/postfix/virtual_alias   virtual_alias_maps = regexp:/etc/postfix/virtual_alias
      
-From thereyou can configure aliases one by one or with regexFor example, I could either do all combinations of oemb (line 1-2, etc.), or the regex for all of them (line 3):+After you enter that blocklet's open the file ''sudo nano /etc/postfix/virtual_alias'' and edit it with every spelling combinationHere's an example:
  
-  /^OEMB1905/    oemb1905 +  /^[Jj][Oo][Nn][Aa][Tt][Hh][Aa][Nn]@haacksnetworking.org/                jonathan 
-  /^Oemb1905/    oemb1905 [and so on ...+  /^[Ww][Ee][Bb][Mm][Aa][Ss][Tt][Ee][Rr]@haacksnetworking.org/            webmaster 
-  /^[Oo][Ee][Mm][Bb]1905oemb1905+ 
 +It's super important to include the domain above after the regex or all emails you send to that begin with your user name will wind up in that user's inbox. When finished configuring, run ''postmap /etc/postfix/virtual_alias'' to honor the changes. So long as everything is working, we can now setup a very reasonable and appropriate way to manage spam, without playing wack-a-mole and without rejecting or discarding emails. Let's first discuss what we can do with postfix itself. It can be configured to reject or discard very poor health emails, such as but not exclusive to setting PTR rules or other fundamentals in ''sudo nano /etc/postfix/main.cf'' as follows: 
 + 
 +  smtpd_sender_restrictions = 
 +      permit_mynetworks, 
 +      permit_sasl_authenticated, 
 +      #reject_unknown_reverse_client_hostname, 
 +      #reject_unknown_client_hostname, 
 +      #reject_unknown_sender_domain, 
 +      #reject_unauthenticated_sender_login_mismatch, 
 +      reject_sender_login_mismatch 
 +      permit 
 +     
 +Personally, I disable most of the above rejects by design. I include them here more for others' reference. Just remember, there's nothing worse than never getting an email. You can also have postfix do expression checking with ''sudo apt install postfix-pcre'' and then edit ''sudo nano /etc/postfix/main.cf'' with expression checking, for example: 
 + 
 +  header_checks = pcre:/etc/postfix/header_checks 
 +  body_checks = pcre:/etc/postfix/body_checks
      
-When finished configuringrun ''postmap /etc/postfix/virtual_alias'' to honor the changes. Alright, to stop spam we are going to use a mix of spamassassin and dovecot-sieve. Let's set up dovecot-sieve first and alert dovecot's delivery agents to its existence. +In these locations, ''sudo nano /etc/postfix/header_checks'' and ''sudo nano /etc/postfix/body_checks'', setup expression checks as follows:
  
-  sudo apt install dovecot-sieve dovecot-managesieved +  /free mortgage quote/    REJECT   
-  sudo nano /etc/dovecot/dovecot.conf+  /free mortgage quote   DISCARD
  
-Set to:+Once they are to your liking, make sure to compile them with ''sudo postmap /etc/postfix/body_checks'' and ''sudo postmap /etc/postfix/header_checks''. Again, in my personal setup, I keep postfix out of the spam-management game. Instead, I prefer to accept ALL email and let spam assassin do the lifting. Let's install spamassasin and integrate it with dovecot's managesieve plugin. Let's do ''sudo apt install dovecot-sieve dovecot-managesieved spamassassin spamc spamass-milter'' and then edit ''sudo nano /etc/dovecot/dovecot.conf'' as follows:
  
   protocols = imap lmtp sieve   protocols = imap lmtp sieve
-   
-Then, open 
- 
-  sudo nano /etc/dovecot/conf.d/15-lda.conf 
  
-Set to:+In ''sudo nano /etc/dovecot/conf.d/15-lda.conf'' please adjust the local delivery agent as follows:
  
   protocol lda {   protocol lda {
Line 364: Line 324:
   }   }
      
-Finally, +Let's also adjust the lmtp agent in ''sudo nano /etc/dovecot/conf.d/20-lmtp.conf'' as follows:
- +
-  sudo nano /etc/dovecot/conf.d/20-lmtp.conf +
- +
-Which should be:+
  
   protocol lmtp {   protocol lmtp {
     mail_plugins = quota sieve     mail_plugins = quota sieve
   }   }
-   
-Once that's done, let's enable regular expression checking of headers and the email body within postfix. I personally don't use these, but I keep them active just in case. 
  
-  sudo apt install postfix-pcre +Now it's time to setup spamassassin in postfix with the other milters. Let's open ''sudo nano /etc/postfix/main.cf'' and adjust the milter block once again:
-  sudo nano /etc/postfix/main.cf +
-  <header_checks = pcre:/etc/postfix/header_checks> +
-  <body_checks = pcre:/etc/postfix/body_checks> +
-   +
-This enables regular expression checking on headers and in the email body. You can enter REJECT or DISCARD as follows: +
- +
-  sudo nano /etc/postfix/header_checks +
-  </free mortgage quote/    REJECT> +
-  sudo nano /etc/postfix/body_checks +
-  </free mortgage quote/    DISCARD> +
-  sudo postmap /etc/postfix/body_checks +
-  sudo postmap /etc/postfix/header_checks +
- +
-Now it's time to setup spamassassin.+
  
-  sudo apt install spamassassin spamc spamass-milter +  milter_default_action = accept 
-  sudo systemctl enable spamassassin +  milter_protocol = 6 
-  sudo systemctl start spamassassin +  smtpd_milters = local:opendkim/opendkim.sock,local:opendmarc/opendmarc.sock,local:spamass/spamass.sock 
-  sudo nano /etc/postfix/main.cf +  non_smtpd_milters = $smtpd_milters
-  <smtpd_milters = local:opendkim/opendkim.sock,local:opendmarc/opendmarc.sock,local:spamass/spamass.sock>+
      
-The milter line above depends on one'setupThis works for me because also use opendkim and opendmarc. Adjust as needed.+It'now time to edit spam assassin's default configuration file in ''sudo nano /etc/default/spamass-milter''As with elsewhere, make sure the REJECT line is commented out, in order to ensure that false positives won't happenIf you understand the risks and want to reject emails at the gate, go ahead and edit ''sudo nano /etc/default/spamass-milter'' and uncomment these lines:
  
-  sudo nano /etc/default/spamass-milter +  #optional custom message 
-  <Make sure the REJECT line is commented out, otherwise false positives won't get delivered.>+  #OPTIONS="-u spamass-milter -i 127.0.0.1 -R SPAM_ARE_NOT_ALLOWED_HERE" 
 +  OPTIONS="-u spamass-milter -i 127.0.0.1" 
 +  #Reject emails with spamassassin scores 15 [or desired score] 
 +  OPTIONS="${OPTIONS} -r 15"
      
-If you prefer to reject then uncomment that lineYou may also optionally add custom message:+Again, I do not use the reject or discard options but rather leverage spam assassin's scoring and header assessing together with dovecot, which can move emails to locations fitting their scoresThere are two fundamental ways to configure the scoring and sieve rules, either with the CLI or with Roundcube. When I first began, I used the CLI and created simple rule in ''sudo nano /etc/dovecot/conf.d/90-sieve.conf'' and entered this block:
  
-  <sudo nano /etc/default/spamass-milter> +  sieve_before = /var/mail/SpamToJunk.sieve
-  OPTIONS="-u spamass-milter -i 127.0.0.1 -R SPAM_ARE_NOT_ALLOWED_HERE"+
      
-Now that dovecot's sieve tool is set up, we can instruct dovecot to use a sieve rule that assesses spam assassin's headers and moves the message to Junk if it meets the specified criteria.  +The sieve_before rule ensures spam assassin assesses the email right after they arrive and before sending them to dovecot and its configured delivery agentsLet's open ''sudo nano /var/mail/SpamToJunk.sieve'' and enter the following:
- +
-  sudo nano /etc/dovecot/conf.d/90-sieve.conf +
-  <sieve_before = /var/mail/SpamToJunk.sieve> +
-   +
-Open the sieve rule with ''sudo nano /var/mail/SpamToJunk.sieve'' and enter the following:+
  
   require "fileinto";   require "fileinto";
Line 425: Line 361:
  
   sudo sievec /var/mail/SpamToJunk.sieve   sudo sievec /var/mail/SpamToJunk.sieve
- 
-[DO NOT DO THIS] Now we can alert postfix to check our spamassassin policy on our behalf. In the ''/etc/postfix/main.cf'' section titled ''smtpd_recipient_restrictions'' add the following line: [DO NOT DO THIS] 
- 
-  <check_policy_service unix:private/spamassassin> 
      
-[DO NOT DO THIS] And over in ''/etc/postfix/master.cf'' enter the following at the bottom: [DO NOT DO THIS] +This rule does one thing. It checks whether spam assassin identified the message as spam, and if so, it uses dovecot to file it in Junk. This means your spam assassin scores and config are what drive the success rate of this sieve rule. It's also important to note that this rule is global, and impacts all user names on the mail server. It's a good approach for the most heinous spam, leaving more customized rules to roundcube's sieve implementation, later in this tutorialLet's open ''sudo nano /etc/spamassassin/local.cf'' and adjust it as follows.
- +
-  spamassassin unix - n n - - pipe +
-  user=debian-spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient} +
- +
-We can now configure some custom scores and white/black lists as needed so ''sudo nano /etc/spamassassin/local.cf'':+
  
   report_contact webmaster@domain.com   report_contact webmaster@domain.com
-  required_score 5.0+  #adjust score below to your use-case 
 +  required_score 5.0 
   #rewrite_header Subject **Possible Spam**   #rewrite_header Subject **Possible Spam**
   report_safe 0   report_safe 0
-  always_add_headers = 1 +  add_header all Spam-Flag _YESNO_ 
-  add_header all Flag _YESNO_ +  add_header all Score _SCORE_
-  add_header all Status "_YESNO_, score=_SCORE_ required=_REQD_ tests=_TESTS_ autolearn=_AUTOLEARN_ version=_VERSION_"+
   add_header all Report _REPORT_   add_header all Report _REPORT_
   add_header all Level _STARS_   add_header all Level _STARS_
 +  add_header all Status "_YESNO_, score=_SCORE_ required=_REQD_ tests=_TESTS_ autolearn=_AUTOLEARN_ version=_VERSION_"
   add_header all Checker-Version "SpamAssassin _VERSION_ (_DATE_) on _HOSTNAME_"   add_header all Checker-Version "SpamAssassin _VERSION_ (_DATE_) on _HOSTNAME_"
 +  #legacy/deprecated header config - do not use, retained for historical record
 +  #always_add_headers = 1
  
-Before we enter the custom scores and white and black listslet's install and enable unboundso that spam-assassin can query the RBLs. RBLs do not allow upstream DNS queriesthus we are required to run our own recursive resolver hereTake care not to expose this publicly. I prefer unbound, but one can also use bind9 or othersSpecify the DNS in the ''local.cf'' and create your rules/lists+I included some header optionswhich can help with debugging. Also, I disable safe reporting and Subject rewriting because they alter the original emailwhich I think is overkill. In order to activate all that spam assassin can do, we need to have our own recursive DNS resolver, required by RBL servicesLet's use the DNS server unbound and install it as follows ''sudo apt install unbound''. It works out of the box, but you can also tweak it by looking at my tutorial here: [[https://wiki.haacksnetworking.org/doku.php?id=computing:unbounddns|Unbound DNS]]. Okay, let's now insruct spamassassin to use our dns server by opening ''sudo nano /etc/spamassassin/local.cf'' and entering the DNS server. We will also add some common scores and white and black lists while at it.
  
-  sudo apt install unbound +  dns_server 127.0.0.1 
-  sudo nano /etc/spamassassin/local.cf +  score MISSING_FROM                      5.0 
-  <dns_server 127.0.0.1> +  score MISSING_DATE                      5.0 
-  <score MISSING_FROM                      5.0> +  score MISSING_HEADERS                   3.0 
-  <score MISSING_DATE                      5.0> +  score PDS_FROM_2_EMAILS                 3.0 
-  <score MISSING_HEADERS                   3.0> +  score FREEMAIL_FORGED_REPLYTO           3.5 
-  <score PDS_FROM_2_EMAILS                 3.0> +  score DKIM_ADSP_NXDOMAIN                5.0 
-  <score FREEMAIL_FORGED_REPLYTO           3.5> +  score FORGED_GMAIL_RCVD                 2.5 
-  <score DKIM_ADSP_NXDOMAIN                5.0> +  score FREEMAIL_FORGED_FROMDOMAIN        3.0 
-  <score FORGED_GMAIL_RCVD                 2.5> +  score HEADER_FROM_DIFFERENT_DOMAINS     3.0 
-  <score FREEMAIL_FORGED_FROMDOMAIN        3.0> +  score FREEMAIL_FROM                     3.0 
-  <score HEADER_FROM_DIFFERENT_DOMAINS     3.0> +  score ACCT_PHISHING                     3.0 
-  <score FREEMAIL_FROM                     3.0> +  score AD_PREFS                          3.0 
-  <score ACCT_PHISHING                     3.0> +  score ADMAIL                            3.0 
-  <score AD_PREFS                          3.0> +  score ADMITS_SPAM                       3.0 
-  <score ADMAIL                            3.0> +  score CONFIRMED_FORGED                  3.0 
-  <score ADMITS_SPAM                       3.0> +  score FROM_PAYPAL_SPOOF                 3.0 
-  <score CONFIRMED_FORGED                  3.0> +  score SPF_SOFTFAIL                      2.0 
-  <score FROM_PAYPAL_SPOOF                 3.0> +  score SPF_FAIL                          5.0 
-  <score SPF_SOFTFAIL                      2.0> +  whitelist_from *@statefarm.com 
-  <score SPF_FAIL                          5.0> +  blacklist_from *@email.freethinkerdaily.com
-  <whitelist_from *@statefarm.com> +
-  <blacklist_from *@email.freethinkerdaily.com>+
  
-Additionally, if you check the full headers, you will see that the RBLs can now be queried without issue. Note that whitelisting adds a -100 score and that blacklisting adds a +100 score. To understand how to tweak the symbolic headers better, one should review their spam and headers periodically and update rules. It is also possible to manage behaviors for whitelist, blacklist, and spam scores after dovecot receives them and from Roundcube. This would be instead of managing them with spam assassin at the CLI before dovecot receives themTo do thatcomment out white and black list rulesand remove the ''sieve_before'' rule we created above. Navigate to roundcube > settings > filters > edit filter set. To replicate the same functionality as above, I created the following:+Additionally, if you check the full headers, you will see that the RBLs can now be queried without issue. Note that whitelisting adds a -100 score and that blacklisting adds a +100 score. To understand how to tweak the symbolic headers better, one should review their spam and headers periodically and update rules based on the headers you see in the full message sourceMake sure to compile the sieve file with ''sievec'' each time you adjust the config, and restart postfix and dovecot. This approach above is good to do for egregiously bad emailbut individual users will likely need their own controls. Sofor larger servers, you can alternately use Roundcube instead. Remember, you must pick one or the other because the ''sieve_before'' rules above will bypass Roundcube's sieve logicBearing this in mind, if you want to use Roundcube for sieve rules, let's navigate to roundcube > settings > filters > edit filter set. To replicate similar functionality as above, I created the following:
  
-  #open roundcube, click the Edit filter set 
-  #copy paste this into the block, replace everything 
   require ["fileinto"];   require ["fileinto"];
   # rule:[whitelist]   # rule:[whitelist]
Line 497: Line 423:
           "bounce-1.public.govdelivery.com"           "bounce-1.public.govdelivery.com"
       ]       ]
 +  ) {
 +      fileinto "Junk";
 +      stop;
 +  }
 +  # rule:[spamcheck]
 +  if anyof (
 +      header :contains "x-spam-status" "Yes",
 +      header :contains "x-spam-flag" "YES",
 +      header :contains "x-spam-level" "*****"
   ) {   ) {
       fileinto "Junk";       fileinto "Junk";
Line 502: Line 437:
   }   }
  
-# rule:[spamcheck] +These rules are processed sequentially. Monitor the Junk folder periodically and refine whitelists as needed. If something escapeslike a full health dirty marketing scamadjust your blacklist. That's all there is to it. Now that spam controls are setupwe need to setup some auditing tools to monitor how well our server is doing these tasksFor postfix, that tool is pflogsumm. Let's install it with ''sudo apt install pflogsumm'' and let's use rsyslog and log rotate to manage the logs, requiring us to also install rsyslog with ''sudo apt install rsyslog''
-if anyof ( +
-    header :contains "x-spam-status" "Yes", +
-    header :contains "x-spam-flag" "YES", +
-    header :contains "x-spam-level" "*****" +
-) { +
-    fileinto "Junk"; +
-    stop; +
-+
- +
- Additionallythe best way to monitor your server is with pflogsum. +
- +
-  sudo apt install pflogsumm +
-  sudo apt install rsyslog+
      
-Disable the ''/var/log/mail.log'' entries that are in ''rsyslog'' and any others that are located in ''/etc/logrotate.d/''Once that's done, create a new rule as follows: +Disable the ''/var/log/mail.log'' entries that are in the ''rsyslog'' logrotate rule in ''/etc/logrotate.d/''This is because we are going to make our own logrotate rule that works nicely with pflogsumm. Create the file ''sudo nano postfix-log'' inside ''/etc/logrotate.d/'' and enter the following:
- +
-  sudo nano postfix-log +
-   +
-In that file, enter the following:+
  
   /var/log/mail.log {   /var/log/mail.log {
Line 532: Line 450:
   }   }
  
-Once that's done, let's create script and cronjob to send us daily reports+Once that's done, let's create script and cronjob to send us daily reports by creating a file ''sudo nano /usr/local/bin/pflog-run.sh'' and entering something like:
- +
-  sudo nano /usr/local/bin/pflog-run.sh +
-   +
-In that script, enter something like this:+
  
   #!/bin/sh   #!/bin/sh
-  #/usr/sbin/logrotate -f /etc/logrotate.d/postfix-log+  #/usr/sbin/logrotate -f /etc/logrotate.d/postfix-log [helpful for manual testing]
   gunzip /var/log/mail.log.0.gz   gunzip /var/log/mail.log.0.gz
   /usr/sbin/pflogsumm /var/log/mail.log.0 --problems-first --rej-add-from --verbose-msg-detail -q |  mail -s "[pflog-lastlog]-$(hostname -f)-$(date)" email@email.com   /usr/sbin/pflogsumm /var/log/mail.log.0 --problems-first --rej-add-from --verbose-msg-detail -q |  mail -s "[pflog-lastlog]-$(hostname -f)-$(date)" email@email.com
Line 553: Line 467:
   30 12 * * * /bin/bash /usr/local/bin/pflog-run.sh >> /home/logs/pflog-run.log   30 12 * * * /bin/bash /usr/local/bin/pflog-run.sh >> /home/logs/pflog-run.log
      
-In extreme casesdirectly block problem domains in postfix in ''/etc/postfix/main.cf'' by adding ''reject_sender example.com'' within the ''smtpd_sender_restrictions ='' blockMake sure to add all users to the mail group.+You can also use the ''-d yesterday'' flag in pflogsumm and wildcard your domainswhich I later found out. But, this works too and I retain its use in my production servers. This ends our primary configuration. If you don't have Roundcube setup, look here: [[https://wiki.haacksnetworking.org/doku.php?id=computing:roundcube|Roundcube Tutorial]]The rest of this tutorial is miscellaneous information that has come up along the way.
  
-  sudo adduser username mail+-------------------------------------------
      
 The SASL module packages should be brought in as dependencies of postfix and/or dovecot. However, on upgrades, etc., they might be removed during dependency resolution. If you get "no sasl" report on your logs suddenly, despite everything working prior, use: The SASL module packages should be brought in as dependencies of postfix and/or dovecot. However, on upgrades, etc., they might be removed during dependency resolution. If you get "no sasl" report on your logs suddenly, despite everything working prior, use:
  
   sudo apt-get install libsasl2-modules   sudo apt-get install libsasl2-modules
 +  
 +If/when things are going wrong, turn on your detailed debugging logs and study them:
 +
 +  nano /etc/dovecot/conf.d/10-logging.conf
 +  <mail_debug yes>
 +  
 +To check record health after you set your DNS records, you can do the following:
 +  
 +  dig txt +short _dmarc.jonathanhaack.com
 +  dig txt +short _dmarc.haacksnetworking.org
 +  dig default._domainkey.jonathanhaack.com txt
 +  dig default._domainkey.haacksnetworking.org txt
 +  dig txt +short jonathanhaack.com
 +  dig txt +short haacksnetworking.org
 +  dig -x 8.28.86.130 +short
 +  dig -x 8.28.86.125 +short
 +  sudo opendkim-testkey -d jonathanhaack.com -s default -vvv
 +  sudo opendkim-testkey -d haacksnetworking.org -s default -vvv
 +  
 +You should test email health with the CLI and/or use a service like [[https://www.mail-tester.com/|Mail Tester]]. I recommend using both CLI to send email and a common client. Both domain.com and mail.domain.com should work if you set everything right. Here's how to send a simple email at the CLI:
 +
 +  echo "Hi, I am testing the subdomain email health." | mail -s "CLI Email Test" oemb1905@jonathanhaack.com
 +  
 +Postfix has its own CLI control tools, such as but not exclusive to viewing email, deleting email, etc.:
 +
 +  mailq
 +  postcat -q E900C4780073
 +  postsuper -d E900C4780073
 +  postsuper -d ALL
 +  
 +These tools prove helpful if/when emails get stuck, etc.
  
- --- //[[alerts@haacksnetworking.org|oemb1905]] 2025/04/08 13:16//+ --- //[[alerts@haacksnetworking.org|oemb1905]] 2025/04/23 20:54//
computing/mailserver.1744118308.txt.gz · Last modified: 2025/04/08 13:18 by oemb1905