0

My emails are going to spam no matter what I do.

Centos 7

Exim

PHP 7.2

Apache 2.4

Hostname and IP are not blacklisted.

Exim config

primary_hostname = mail.example.com
domainlist local_domains = @ : example.com
domainlist relay_to_domains =
hostlist   relay_from_hosts = localhost
acl_smtp_mail =         acl_check_mail
acl_smtp_rcpt =         acl_check_rcpt
.ifdef _HAVE_PRDR
acl_smtp_data_prdr =    acl_check_prdr
.endif
acl_smtp_data =         acl_check_data
acl_smtp_mime =         acl_check_mime
av_scanner = clamd:/var/run/clamd.exim/clamd.sock
tls_advertise_hosts = *
tls_certificate = /etc/ssl/mail.example.com.crt
tls_privatekey = /etc/ssl/mail.example.com.key
daemon_smtp_ports = 25 : 465 : 587
tls_on_connect_ports = 465
never_users = root
host_lookup = *
auth_advertise_hosts = *
dns_dnssec_ok = 1
.ifdef _HAVE_PRDR
prdr_enable = true
.endif
log_selector = +smtp_protocol_error +smtp_syntax_error \
        +tls_certificate_verified
ignore_bounce_errors_after = 2d
timeout_frozen_after = 7d
keep_environment = ^LDAP
add_environment = PATH=/usr/bin::/bin
begin acl
acl_check_mail:
  deny condition = ${if eq{$sender_helo_name}{} {1}}
       message = Nice boys say HELO first
  warn condition = ${if eq{$sender_host_name}{} {1}}
       set acl_m_greylistreasons = Host $sender_host_address lacks reverse DNS\n$acl_m_greylistreasons
  accept
acl_check_rcpt:
  accept  hosts = :
          control = dkim_disable_verify
  deny    message       = Restricted characters in address
          domains       = +local_domains
          local_parts   = ^[.] : ^.*[@%!/|]
  deny    message       = Restricted characters in address
          domains       = !+local_domains
          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
  accept  local_parts   = postmaster
          domains       = +local_domains
  require verify        = sender
  accept  hosts         = +relay_from_hosts
          control       = submission
          control       = dkim_disable_verify
  accept  authenticated = *
          control       = submission
          control       = dkim_disable_verify
  require message       = nice hosts say HELO first
          condition     = ${if def:sender_helo_name}
  require message = relay not permitted
          domains = +local_domains : +relay_to_domains
  require verify = recipient
  accept
.ifdef _HAVE_PRDR
acl_check_prdr:
  warn  set acl_m_did_prdr = y
.endif
  accept
acl_check_data:
  deny    message    = maximum allowed line length is 998 octets, \
                       got $max_received_linelength
          condition  = ${if > {$max_received_linelength}{998}}
  deny    !verify =     header_syntax
          message =     header syntax
          log_message = header syntax ($acl_verify_message)
  warn    condition  = ${if !def:h_Message-ID: {1}}
          set acl_m_greylistreasons = Message lacks Message-Id: header. Consult RFC2822.\n$acl_m_greylistreasons
  accept
acl_check_mime:
  deny message = Blacklisted file extension detected
       condition = ${if match \
                        {${lc:$mime_filename}} \
                        {\N(\.exe|\.pif|\.bat|\.scr|\.lnk|\.com)$\N} \
                     {1}{0}}
  accept
begin routers
.ifdef ROUTER_SMARTHOST
smarthost:
  driver = manualroute
  domains = ! +local_domains
  transport = smarthost_smtp
  route_data = ROUTER_SMARTHOST
  ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
  no_more
.else
dnslookup:
  driver = dnslookup
  domains = ! +local_domains
  transport = remote_smtp
  ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
  dnssec_request_domains = *
  no_more
.endif
system_aliases:
  driver = redirect
  allow_fail
  allow_defer
  data = ${lookup{$local_part}lsearch{/etc/aliases}}
  file_transport = address_file
  pipe_transport = address_pipe
userforward:
  driver = redirect
  check_local_user
  file = $home/.forward
  allow_filter
  no_verify
  no_expn
  check_ancestor
  file_transport = address_file
  pipe_transport = address_pipe
  reply_transport = address_reply
procmail:
  driver = accept
  check_local_user
  require_files = ${local_part}:+${home}/.procmailrc:/usr/bin/procmail
  transport = procmail
  no_verify
localuser:
  driver = accept
  check_local_user
  transport = local_delivery
  cannot_route_message = Unknown user
begin transports
remote_smtp:
  driver = smtp
  message_size_limit = ${if > {$max_received_linelength}{998} {1}{0}}
.ifdef _HAVE_DANE
  dnssec_request_domains = *
  hosts_try_dane = *
.endif
.ifdef _HAVE_PRDR
  hosts_try_prdr = *
.endif
remote_msa:
  driver = smtp
  port = 587
  hosts_require_auth = *
procmail:
  driver = pipe
  command = "/usr/bin/procmail -d $local_part"
  return_path_add
  delivery_date_add
  envelope_to_add
  user = $local_part
  initgroups
  return_output
smarthost_smtp:
  driver = smtp
  message_size_limit = ${if > {$max_received_linelength}{998} {1}{0}}
  multi_domain
.ifdef _HAVE_TLS
  hosts_require_tls = *
  tls_verify_hosts = *
  tls_try_verify_hosts = *
  tls_sni = ROUTER_SMARTHOST
.ifdef _HAVE_OPENSSL
  tls_require_ciphers = HIGH:!aNULL:@STRENGTH
.endif
.ifdef _HAVE_GNUTLS
  tls_require_ciphers = SECURE192:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1
.endif
.endif
.ifdef _HAVE_PRDR
  hosts_try_prdr = *
.endif
local_delivery:
  driver = appendfile
  directory = $home/Maildir
  maildir_format
  maildir_use_size_file
  delivery_date_add
  envelope_to_add
  return_path_add
  group = mail
  mode = 0660
address_pipe:
  driver = pipe
  return_output
address_file:
  driver = appendfile
  delivery_date_add
  envelope_to_add
  return_path_add
address_reply:
  driver = autoreply
begin retry
*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h
begin rewrite
begin authenticators

httpd config

ServerRoot "/etc/httpd"
Listen 80
Include conf.modules.d/*.conf
User apache
Group apache
ServerAdmin root@localhost
<Directory />
    AllowOverride none
    Require all denied
</Directory>
DocumentRoot "/var/www/html"
<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>
<Directory "/var/www/html">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>
<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>
<Files ".ht*">
    Require all denied
</Files>
ErrorLog "logs/error_log"
LogLevel warn
<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
    CustomLog "logs/access_log" combined
</IfModule>
<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
</Directory>
<IfModule mime_module>
    TypesConfig /etc/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
    AddType text/html .shtml
    AddOutputFilter INCLUDES .shtml
</IfModule>
AddDefaultCharset UTF-8
<IfModule mime_magic_module>
    MIMEMagicFile conf/magic
</IfModule>
EnableSendfile on
<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / http://www.example.com/
</VirtualHost>
<VirtualHost *:80>
    DocumentRoot /var/www/domain
    ServerName www.example.com
</VirtualHost>
IncludeOptional conf.d/*.conf

php.ini

[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
expose_php = On
max_execution_time = 30
max_input_time = 60
memory_limit = 128M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
html_errors = On
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 8M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
enable_dl = Off
file_uploads = On
upload_max_filesize = 2M
max_file_uploads = 20
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
[CLI Server]
cli_server.color = On
[Date]
[filter]
[iconv]
[imap]
[intl]
[sqlite3]
[Pcre]
pcre.jit=0
[Pdo]
[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=
[Phar]
[mail function]
sendmail_path = /usr/sbin/sendmail -t -i
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[Interbase]
ibase.allow_persistent = 1
ibase.max_persistent = -1
ibase.max_links = -1
ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
ibase.dateformat = "%Y-%m-%d"
ibase.timeformat = "%H:%M:%S"
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[browscap]
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = -1
[mbstring]
[gd]
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
[ldap]
ldap.max_links = -1
[dba]
[curl]
[openssl]

Email Header

Delivered-To: me@gmail.com
Received: by 2002:a2e:98d0:0:0:0:0:0 with SMTP id s16csp1166605ljj;
        Fri, 23 Aug 2019 14:06:37 -0700 (PDT)
X-Google-Smtp-Source: APXvYqyOxkRrPQhtHGeKYbbO9Lg0kk1NOVrMmutp3e0k8bPOswf6pDpSQAKX+Mc7UfWiXgA1XssJ
X-Received: by 2002:a37:805:: with SMTP id 5mr6101878qki.351.1566594397253;
        Fri, 23 Aug 2019 14:06:37 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1566594397; cv=none;
        d=google.com; s=arc-20160816;
        b=0K4dayeP8vkS4n+SsDW0VidOGP53vDjp8ifWoz4p/NUWvmgTKxxvZNowOgshN56B5q
         sDE++dR0rG3I9yDDrnqzSUOHfG57K4wemAakC/rXG9NX3n+CiIhhh29LeRGdO2dzWusi
         mkVdslT7utmSfzF3/irEGb7Tc0MbqigCbtxiE4sRT/av2MSX/48lnhivsbZy2Aaw0W5c
         lBUmZbLYBWVEufdMgGhp4EdxlG86rJDLfSgx0ctUodqmtd3S8oo2Mq+tp8JMmrW3UQmt
         F2lH4xU+qRZCPkQsOP9+eJpHptSkyB9SM7iwxJ5qQT7OV6LUCysMM04IEG3bNu1my1M4
         LPbg==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=date:message-id:from:subject:to;
        bh=z6TUz85EdYrACGMHYgZhJGvVy5oQI0dooVMKa2ZT7c4=;
        b=gJesyqL/WZr8201yzIScrS1g+bAshQ38krV/dpnRisDryRlVqeB09r/b7FTHPpb87f
         atRQv0WSrc6m9f/NYVbicJ8Evfc3cCoI4UKVA+Jytm4gfed7lJMpTBEniBGozEQ78Tq7
         Ibkl86tejCUUDrXCTZXWQBDRbxyml/x5NnCSrcJlx+3QVavwBnZWmRamPrDqQPl5ALG9
         vrbWP7afqzPkTEvfoVUpDaqdiF7A2I77NEwqljxx96mASMRFrka3NTyOJIOKGJM2oQcL
         YqG5fIb/1lRz5u2z7LeHGrNdGkIkZ5BwEkXIXRzLnFOBHGUd8VyTY/wPjvzo4oI/XhWx
         JMNw==
ARC-Authentication-Results: i=1; mx.google.com;
       spf=pass (google.com: domain of root@mail.example.com designates 157.245.6.214 as permitted sender) smtp.mailfrom=root@mail.example.com;
       dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com
Return-Path: <root@mail.example.com>
Received: from mail.example.com (mail.example.com. [157.245.6.214])
        by mx.google.com with ESMTPS id v81si2604067qka.27.2019.08.23.14.06.36
        for <brian.curless1@gmail.com>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Fri, 23 Aug 2019 14:06:37 -0700 (PDT)
Received-SPF: pass (google.com: domain of root@mail.example.com designates 157.245.6.214 as permitted sender) client-ip=157.245.6.214;
Authentication-Results: mx.google.com;
       spf=pass (google.com: domain of root@mail.example.com designates 157.245.6.214 as permitted sender) smtp.mailfrom=root@mail.example.com;
       dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com
Received: from root by mail.example.com with local (Exim 4.92) (envelope-from <root@mail.example.com>) id 1i1GlY-0001a2-Pn for brian.curless1@gmail.com; Fri, 23 Aug 2019 21:06:36 +0000
To: brian.curless1@gmail.com
Subject: My subject
From: afornito@example.com
Message-Id: <E1i1GlY-0001a2-Pn@mail.example.com>
Date: Fri, 23 Aug 2019 21:06:36 +0000

Hello world!

All mxtoolbox checks pass

enter image description here

1

Modern spam filters use different signals to classify an email. How exactly it is done differs by implementation, but in general the sender only has indirect control over many of those. Just because an email system is cleanly implemented, does not mean it won't be sending spam; using that as the only signal would defeat the purpose.

SPF and DKIM ensure that the email was emitted by the owning system, preventing spammers from abusing random addresses. A valid rDNS suggests that you actually have some control over the IP you're sending from. Then there are blacklists, which some systems, e.g. SpamAssassin, query to identify known bad senders. Large email services often keep statistics on a sender through their own users feedback. If enough people hit the "spam button" on the first messages of a campaign, it's likely to end up in the spam folder for everyone else. Some mail providers share IP reputation data with third party services, which in return provide a more detailed analysis of a sender. Content analysis also plays a role. If an individual message contains questionable content (think Viagra), it may get classified as spam despite originating from a reputable sender. Sending large amounts of mail to non-existing addresses, i.e. using dirty lists, is another hallmark of spammers and has a negative impact on reputation, too. In a nutshell, being trusted by the major providers like GMail, Yahoo or MSN takes time and consistent sending of quality content that recipients actually want, and won't get flagged by users or content analysis.

If you use an address from a VPS hoster, where IPs are a dime a dozen and change ownership often, you'll start out with rather low trust. Use reputation and blacklist checks to ensure the IP doesn't already have a bad history. If it does, contact the list maintainers where possible, and explain that the IP is under new ownership. Most will allow a fresh start.

If you send bulk email, you can also participate in feedback loops to remove people who classify your messages as spam from your list, and as such avoid the associated penalties in the future.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.