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: [email protected]
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 [email protected] designates 157.245.6.214 as permitted sender) [email protected];
dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com
Return-Path: <[email protected]>
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 <[email protected]>
(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 [email protected] 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 [email protected] designates 157.245.6.214 as permitted sender) [email protected];
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 <[email protected]>) id 1i1GlY-0001a2-Pn for [email protected]; Fri, 23 Aug 2019 21:06:36 +0000
To: [email protected]
Subject: My subject
From: [email protected]
Message-Id: <[email protected]>
Date: Fri, 23 Aug 2019 21:06:36 +0000
Hello world!
All mxtoolbox checks pass
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.