0. conf/domainlist.xml
메일서버에서 사용하는 도메인을 지정해준다. 아래 설정에서는 두개의 도메인을 사용하는 것을 기준으로 했다.
jongwan.com another-domain.com
<?xml version="1.0"?>
<domainlist class="org.apache.james.domainlist.jpa.JPADomainList">
<autodetect>false</autodetect>
<autodetectIP>false</autodetectIP>
<defaultDomain>jongwan.com</defaultDomain>
<domainnames>
<domainname>jongwan.com</domainname>
<domainname>another-domain.com</domainname>
</domainnames>
</domainlist>
defaultDomain : 기본 도메인을 지정한다. domainname 항목중에 하나를 지정한다. domainnames.domainname : 사용할 도메인을 추가한다. domainname 항목을 추가해서 여러개의 도메인을 사용할 수 있다.
1. conf/dnsservice.xml
DNS 서버를 지정한다. 자동으로 했을 때 문제가 있어 강제로 지정했다.
<?xml version="1.0"?>
<dnsservice>
<servers>
<server>1.1.1.1</server>
</servers>
<autodiscover>false</autodiscover>
<authoritative>false</authoritative>
<maxcachesize>50000</maxcachesize>
</dnsservice>
autodiscover : 기본값은 true인데, 동작을 잘 안해서 변경했다. servers.server : 1.1.1.1로 강제 지정했다.
2. keystore
TLS사용을 위해서 키를 생성한다. smtpserver.xml, imapserver.xml에서 사용한다.
/usr/local/james 위치에 설치기준
keytool -genkey -alias james -keyalg RSA -storetype PKCS12 -keystore /usr/local/james/conf/keystore
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: Jongwan Kim
What is the name of your organizational unit?
[Unknown]: None
What is the name of your organization?
[Unknown]: None
What is the name of your City or Locality?
[Unknown]: Seoul
What is the name of your State or Province?
[Unknown]: Guro-gu
What is the two-letter country code for this unit?
[Unknown]: KR
Is CN=Jongwan Kim, OU=None, O=None, L=Seoul, ST=Guro-gu, C=KR correct?
[no]: y
3. conf/smtpserver.xml
메일 발송을 위한 SMTP 설정을 한다. 25번 포트와 465번 포트설정이 각각 smtpserver 항목으로 있다.
<?xml version="1.0"?>
<smtpservers>
<smtpserver enabled="true">
<jmxName>smtpserver</jmxName>
<bind>0.0.0.0:25</bind>
<connectionBacklog>200</connectionBacklog>
<tls socketTLS="false" startTLS="false">
<keystore>file://conf/keystore</keystore>
<keystoreType>PKCS12</keystoreType>
<secret>123456</secret>
<provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
<algorithm>SunX509</algorithm>
</tls>
<connectiontimeout>360</connectiontimeout>
<connectionLimit>0</connectionLimit>
<connectionLimitPerIP>0</connectionLimitPerIP>
<auth>
<plainAuthEnabled>true</plainAuthEnabled>
</auth>
<authorizedAddresses>127.0.0.0/24, 192.168.0.0/24, 100.100.100.0/24</authorizedAddresses>
<maxmessagesize>0</maxmessagesize>
<addressBracketsEnforcement>true</addressBracketsEnforcement>
<handlerchain>
<handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
<handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
</handlerchain>
</smtpserver>
<smtpserver enabled="true">
<jmxName>smtpservertls</jmxName>
<bind>0.0.0.0:465</bind>
<connectionBacklog>200</connectionBacklog>
<tls socketTLS="false" startTLS="true">
<keystore>file://conf/keystore</keystore>
<keystoreType>PKCS12</keystoreType>
<secret>123456</secret>
<provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
<algorithm>SunX509</algorithm>
</tls>
<connectiontimeout>360</connectiontimeout>
<connectionLimit>0</connectionLimit>
<connectionLimitPerIP>0</connectionLimitPerIP>
<auth>
<plainAuthEnabled>true</plainAuthEnabled>
</auth>
<authorizedAddresses>127.0.0.0/24, 192.168.0.0/24, 100.100.100.0/24</authorizedAddresses>
<maxmessagesize>0</maxmessagesize>
<addressBracketsEnforcement>true</addressBracketsEnforcement>
<handlerchain>
<handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
<handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
</handlerchain>
</smtpserver>
</smtpservers>
jmxName : smtpserver, smtpservertls 두가지 항목이 각각 smtpserver 항목에 있다. smtpserver 항목마다 jmxName이 달라야 오류가 발생하지 않는다. bind : 각각 0.0.0.0:25, 0.0.0.0:465 을 설정한다. tls : 465포트를 사용하는 0.0.0.0:465에 대해서 startTLS=”true” 를 변경 tls.keystore : /usr/local/james/ 폴더를 기준으로 이전에 생성한 keystore를 지정해준다. tls.secret : keystore 생성시 사용한 비밀번호 authorizedAddresses : 인증없이 접속가능한 아이피 대역을 쉼표 기준으로 입력한다.
4. imapserver.xml
IMAP 사용을 위해서 143, 993 포트 설정을 한다. imapserver 항목으로 추가가 가능하다.
<?xml version="1.0"?>
<imapservers>
<imapserver enabled="true">
<jmxName>imapserver</jmxName>
<bind>0.0.0.0:143</bind>
<connectionBacklog>200</connectionBacklog>
<tls socketTLS="false" startTLS="false">
<keystore>file://conf/keystore</keystore>
<keystoreType>PKCS12</keystoreType>
<secret>123456</secret>
<provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
</tls>
<connectionLimit>0</connectionLimit>
<connectionLimitPerIP>0</connectionLimitPerIP>
<plainAuthDisallowed>false</plainAuthDisallowed>
<auth>
<plainAuthEnabled>true</plainAuthEnabled>
</auth>
</imapserver>
<imapserver enabled="true">
<jmxName>imapservertls</jmxName>
<bind>0.0.0.0:993</bind>
<connectionBacklog>200</connectionBacklog>
<tls socketTLS="false" startTLS="true">
<keystore>file://conf/keystore</keystore>
<keystoreType>PKCS12</keystoreType>
<secret>123456</secret>
<provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
</tls>
<connectionLimit>0</connectionLimit>
<connectionLimitPerIP>0</connectionLimitPerIP>
<plainAuthDisallowed>false</plainAuthDisallowed>
<auth>
<plainAuthEnabled>true</plainAuthEnabled>
</auth>
</imapserver>
</imapservers>
imapserver.jmxName : 143, 993 두가지 항목에 대해서 이름을 다르게 지정한다. tls : 993 포트 지정시 startTLS=”true” 로 변경 tls.keystore : 위에서 생성한 keystore를 지정해준다. plainAuthDisallowed : 기본값은 true 이고, 외부에서 접속시 암호화 없는 비밀번호를 사용하려고 false로 변경했다.
5. pop3server.xml
POP3는 사용하지 않는다.
<?xml version="1.0"?>
<pop3servers>
<pop3server enabled="false"
</pop3servers>
pop3server : 사용하지 않으려고 enabled=”false”로 변경
6. mailetcontainer.xml
메일 송/수신관련된 복잡한 설정이 있다.
<?xml version="1.0"?>
<mailetcontainer enableJmx="true">
<context>
<postmaster>me@jongwan.com</postmaster>
</context>
<spooler>
<threads>20</threads>
<errorRepository>file://var/mail/error/</errorRepository>
</spooler>
<processors>
<processor state="root" enableJmx="true">
<mailet match="All" class="PostmasterAlias"/>
<mailet match="RelayLimit=30" class="Null"/>
<mailet match="HasMailAttribute=spamChecked" class="ToProcessor">
<processor>transport</processor>
</mailet>
<mailet match="All" class="SetMailAttribute">
<spamChecked>true</spamChecked>
</mailet>
<mailet match="SMTPAuthSuccessful" class="ToProcessor">
<processor>transport</processor>
</mailet>
<mailet match="All" class="ToProcessor">
<processor>transport</processor>
</mailet>
</processor>
<processor state="error" enableJmx="true">
<mailet match="All" class="ToRepository">
<repositoryPath>file://var/mail/error/</repositoryPath>
</mailet>
</processor>
<processor state="transport" enableJmx="true">
<mailet match="SenderIsRegex=(.*)@jongwan\.com" class="org.apache.james.jdkim.mailets.DKIMSign">
<signatureTemplate>v=1; s=mail; d=jongwan.com ; h=from : reply-to : subject : date : to : cc : resent-date : resent-from : resent-sender : resent-to : resent-cc : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; a=rsa-sha256; bh=; b=;</signatureTemplate>
<privateKey>
-----BEGIN RSA PRIVATE KEY-----
# 여기에 Private Key 입력
-----END RSA PRIVATE KEY-----
</privateKey>
</mailet>
<mailet match="SenderIsRegex=(.*)@another-domain\.com" class="org.apache.james.jdkim.mailets.DKIMSign">
<signatureTemplate>v=1; s=mail; d=another-domain.com ; h=from : reply-to : subject : date : to : cc : resent-date : resent-from : resent-sender : resent-to : resent-cc : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; a=rsa-sha256; bh=; b=;</signatureTemplate>
<privateKey>
-----BEGIN RSA PRIVATE KEY-----
# 여기에 Private Key 입력
-----END RSA PRIVATE KEY-----
</privateKey>
</mailet>
<mailet match="SMTPAuthSuccessful" class="SetMimeHeader">
<name>X-UserIsAuth</name>
<value>true</value>
<onMailetException>ignore</onMailetException>
</mailet>
<mailet match="HasMailAttribute=org.apache.james.SMIMECheckSignature" class="SetMimeHeader">
<name>X-WasSigned</name>
<value>true</value>
<onMailetException>ignore</onMailetException>
</mailet>
<mailet match="All" class="RecipientRewriteTable" />
<mailet match="RecipientIsLocal" class="Sieve"/>
<mailet match="RecipientIsLocal" class="AddDeliveredToHeader"/>
<mailet match="RecipientIsLocal" class="LocalDelivery"/>
<mailet match="HostIsLocal" class="ToProcessor">
<processor>local-address-error</processor>
<notice>550 - Requested action not taken: no such user here</notice>
</mailet>
<mailet match="All" class="RemoteDelivery">
<outgoing>outgoing</outgoing>
<startTLS>true</startTLS>
<mail.smtp.ssl.trust>*</mail.smtp.ssl.trust>
<delayTime>5000, 100000, 500000</delayTime>
<maxRetries>3</maxRetries>
<maxDnsProblemRetries>0</maxDnsProblemRetries>
<deliveryThreads>10</deliveryThreads>
<sendpartial>true</sendpartial>
<bounceProcessor>bounces</bounceProcessor>
</mailet>
</processor>
<processor state="over-quota" enableJmx="true">
<mailet match="All" class="MetricsMailet">
<metricName>mailet-over-quota-error</metricName>
</mailet>
<mailet match="All" class="Bounce">
<message>The following recipients do not have enough space for storing the email you sent them.</message>
<attachment>none</attachment>
</mailet>
<mailet match="All" class="ToRepository">
<repositoryPath>file://var/mail/over-quota-error/</repositoryPath>
</mailet>
</processor>
<processor state="spam" enableJmx="true">
<mailet match="All" class="ToRepository">
<repositoryPath>file://var/mail/spam/</repositoryPath>
</mailet>
</processor>
<processor state="virus" enableJmx="true">
<mailet match="All" class="SetMailAttribute">
<org.apache.james.infected>true, bouncing</org.apache.james.infected>
</mailet>
<mailet match="SMTPAuthSuccessful" class="Bounce">
<inline>heads</inline>
<attachment>none</attachment>
<notice>Warning: We were unable to deliver the message below because it was found infected by virus(es).</notice>
</mailet>
<mailet match="All" class="Null" />
</processor>
<processor state="local-address-error" enableJmx="true">
<mailet match="All" class="ToRepository">
<repositoryPath>file://var/mail/address-error/</repositoryPath>
</mailet>
</processor>
<processor state="relay-denied" enableJmx="true">
<mailet match="All" class="ToRepository">
<repositoryPath>file://var/mail/relay-denied/</repositoryPath>
</mailet>
</processor>
<processor state="bounces" enableJmx="true">
<mailet match="All" class="DSNBounce">
<passThrough>false</passThrough>
</mailet>
</processor>
</processors>
</mailetcontainer>
기본설정에서 변경된 부분만 설명한다.
<mailet match="SenderIsRegex=(.*)@jongwan\.com" class="org.apache.james.jdkim.mailets.DKIMSign">
<signatureTemplate>v=1; s=mail; d=jongwan.com ; h=from : reply-to : subject : date : to : cc : resent-date : resent-from : resent-sender : resent-to : resent-cc : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; a=rsa-sha256; bh=; b=;</signatureTemplate>
<privateKey>
-----BEGIN RSA PRIVATE KEY-----
# 여기에 Private Key 입력
-----END RSA PRIVATE KEY-----
</privateKey>
</mailet>
DKIM 설정을 위해서 <processor state=”transport”> 항목의 가장위에 추가 한다. 도메인별로 키가 다르므로 match=”SenderIsRegex=…” 를 사용해서 발송시 도메인별로 헤더를 다르게 추가해준다.
<mailet match="All" class="RemoteDelivery">
...
<startTLS>true</startTLS>
<mail.smtp.ssl.trust>*</mail.smtp.ssl.trust>
...
</mailet>
구글메일에서 위와같이 나올경우
위처럼 암호화관련 경고나 나오면 <startTLS>true</startTLS>를 추가한다.
직접 생성한 인증서를 사용해서 경고가 나올 경우 <mail.smpt.ssl.trust>*</mail.smpt.ssl.trust> 항목을 추가한다.
외부로 메일발송 허용
<mailet match="RemoteAddrNotInNetwork=127.0.0.1" class="ToProcessor">
<processor>relay-denied</processor>
<notice>550 - Requested action not taken: relaying denied</notice>
</mailet>
이 규칙이 있으면 외부로 메일이 발송되지 않는다. 내부메일서버로만 사용한다면 놔두고, 외부로 메일발송이 필요하다면 주석 처리해야한다.