首先要安裝 James Server 3.0
可以參考 Quick Start
1: 先確認系統環境,必須有安裝JDK 1.5+
2: 下載james-server-container-spring-3.0-M2-bin.zip ,並解壓到指定資料夾(EX c:\)
然後要做一些設定,James 3.0 版本在設定上分成多個XML
相關XML的細節可參考 Configure James Server , 這邊只針對幾個設定做說明
打開cmd 輸入ipconfig /all , 查看local 的DNS設定
打開{yourJamesServerPath}\conf\dnsservice.xml ,設定如下
dnsservice.xml 相關的設定如下:
<!-- DNS Service Block -->
<!-- -->
<!-- Specifies DNS Server information for use by various components inside -->
<!-- James. -->
<!-- -->
<!-- If autodiscover is true, James will attempt to autodiscover the DNS servers configured on your underlying system.-->
<!-- Currently, this works if the OS has a unix-like /etc/resolv.conf,-->
<!-- or the system is Windows based with ipconfig or winipcfg.-->
<!-- -->
<!-- If no DNS servers are found and you have not specified any below, 127.0.0.1 will be used-->
<!-- If you use autodiscover and add DNS servers manually a combination of all the dns servers will be used -->
<!-- -->
<!-- Information includes a list of DNS Servers to be used by James. These are -->
<!-- specified by the server elements, each of which is a child element of the -->
<!-- servers element. Each server element is the IP address of a single DNS server. -->
<!-- The servers element can have multiple server children. -->
<dnsservice>
<servers>
<!--Enter ip address of your DNS server, one IP address per server -->
<!-- element. -->
<!--
<server>127.0.0.1</server>
-->
</servers>
<!-- Change autodiscover to false if you would like to turn off autodiscovery -->
<!-- and set the DNS servers manually in the <servers> section -->
<autodiscover>true</autodiscover>
<authoritative>false</authoritative>
<!-- Maximum number of entries to maintain in the DNS cache -->
<maxcachesize>50000</maxcachesize>
<!-- Uncomment this if you want James to try a single server for each -->
<!-- multihomed mx host. -->
<!--
<singleIPperMX> true </singleIPperMX>
-->
</dnsservice>
打開{yourJamesServerPath}\conf\domainlist.xml, 設定如下,這邊主要設定dns namespace identifies
以下是domainlist.xml的說明
<!-- Domainnames identifies the DNS namespace served by this instance of James. -->
<!-- These domainnames are used for both matcher/mailet processing and SMTP auth -->
<!-- to determine when a mail is intended for local delivery. -->
<!-- -->
<!-- If autodetect is TRUE, James wil attempt to discover its own host name AND -->
<!-- use any explicitly specified servernames. -->
<!-- If autodetect is FALSE, James will use only the specified domainnames. -->
<!-- -->
<!-- If autodetectIP is not FALSE, James will also allow add the IP address for each servername. -->
<!-- The automatic IP detection is to support RFC 2821, Sec 4.1.3, address literals. -->
<!-- -->
<!-- To override autodetected domainames names simply add explicit domainname elements. -->
<!-- In most cases this will be necessary. -->
<!-- By default, the domainname 'localhost' is specified. This can be removed, if required. -->
<!-- -->
<!-- Warning: If you are using fetchmail it is important to include the -->
<!-- fetched domains in the server name list to prevent looping. -->
<domainlists>
<!-- XML based DomainList implementation -->
<domainlist class="org.apache.james.domainlist.xml.XMLDomainList">
<domainnames>
<domainname>localhost</domainname>
</domainnames>
<autodetect>true</autodetect>
<autodetectIP>true</autodetectIP>
</domainlist>
<!-- JPA implementation for DomainList -->
<!--
<domainlist class="org.apache.james.domainlist.jpa.JPADomainList">
<autodetect>true</autodetect>
<autodetectIP>true</autodetectIP>
</domainlist>
-->
<!-- JDBC implementation for DomainList. This is deprecated and should not be used. -->
<!-- Use JPADomainList if you need a db backend DomainList -->
<!--
<domainlist class="org.apache.james.domainlist.jdbc.JDBCDomainList">
<repositoryPath>db://maildb/domain</repositoryPath>
<sqlFile>file://conf/sqlResources.xml</sqlFile>
<autodetect>true</autodetect>
<autodetectIP>true</autodetectIP>
</domainlist>
-->
</domainlists>
修改C:\WINDOWS\system32\drivers\etc\hosts , 增加domain & ip mapping
打開{yourJamesServerPath}\conf\mailserver.xml, 設定如下
defaultDomain 為預設的domain name, 設成mydomain.james
postmaster設為Postmaster@mydomain.james , 如果新增一個user 叫AAA ,那mail位置就為AAA@mydomain.james
mailserver.xml的相關設定說明
<mailserver>
<!-- CHECKME! -->
<!-- This is the postmaster email address for this mail server. -->
<!-- Set this to the appropriate email address for error reports -->
<!-- If this is set to a non-local email address, the mail server -->
<!-- will still function, but will generate a warning on startup. -->
<postmaster>Postmaster@localhost</postmaster>
<!-- Set to true to support virtualHosting. If virtualHosting support is enabled the server will accept thread every user independ on -->
<!-- domain level. -->
<enableVirtualHosting> false </enableVirtualHosting>
<!-- Set the default domain which will be used if an email is send to a recipient without a domain part -->
<!-- If not defaultdomain is set the first domain of the DomainList get used -->
<defaultDomain> localhost </defaultDomain>
<!-- This is the name used by the server to identify itself in the RemoteManager -->
<!-- protocol. If autodetect is TRUE, the server will discover its -->
<!-- own host name and use that in the protocol. If discovery fails, -->
<!-- the value of 'localhost' is used. If autodetect is FALSE, James -->
<!-- will use the specified value. -->
<!-- Set the default helloName which is used in all services if not overridden in the specific service-->
<helloName autodetect="true">myMailServer</helloName>
</mailserver>
然後在cmd 下進入{yourJamesServerPath}\bin, 輸入james install, 安裝james
再輸入james start , 會啟動james server,如下圖所示:
然後輸入telnet mydomain.james 4555 ,連進admin設定, 預設的acct/passwd 都是root
進入後可以新增user , 使用adduser [acctname] [passwd] , 新增一個test , 位置就是test@mydomain.james
然後可以telnet 到mydomain.james 25 做動作,但這邊我用outlook 收發mail
設定如下,
就能正常的收發信了(外信如gmail要發到內部domain這邊不在處理範圍內:p )
再來就是主要的Mailet & Matcher , Mailet API是一個用來做郵件處理程序的簡單的API。 James是Mailet的容器,通過Mailet(定制的或已有的)完成各種複雜的郵件處理任務,類似Servlet ,
這邊用Maven Create 一個sample Maven Project , pom.xml如下
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.my.james</groupId> <artifactId>MyJames.Mailet</artifactId> <version>1.0.0</version> <dependencies> <dependency> <groupId>james</groupId> <artifactId>james</artifactId> <version>3.0a1</version> </dependency> <dependency> <groupId>org.apache.james</groupId> <artifactId>apache-mailet-base</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>james</groupId> <artifactId>mailet-api</artifactId> <version>3.0</version> </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.1</version> </dependency> </dependencies> </project>
Mailet 的部份
com.mypackage.mailets.FilterByMailet
package com.mypackage.mailets;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.apache.mailet.Mail;
import org.apache.mailet.MailAddress;
import org.apache.mailet.base.GenericMailet;
/**
* @author momo
*
*/
public class FilterByMailet extends GenericMailet {
@Override
public void init(){
this.log("===> test for FilterByMailet init()");
System.out.println("===> test for FilterByMailet init()");
}
public void service(Mail mail) throws MessagingException {
this.log("");
try {
this.log("====> MailetInfo =" this.getMailetInfo());
System.out.println("====> MailetInfo =" this.getMailetInfo());
// TODO Auto-generated method stub
this.log("====> sender = " mail.getSender().toString());
Collection c = mail.getRecipients();
Iterator it = c.iterator();
if (it.hasNext()) {
MailAddress recipient = (MailAddress) it.next();
this.log("====> recipient = " recipient.toString());
}
MimeMessage msg = mail.getMessage();
this.log("====> subject = " msg.getSubject());
this.log("====> contentType = " msg.getContentType());
if (msg.getContent() instanceof MimeMultipart) {
MimeMultipart content = (MimeMultipart) msg.getContent();
for (int i = 0; i < content.getCount(); i ) {
BodyPart p = content.getBodyPart(i);
this.log(i ".n" p.getContentType() "n"
p.getContent());
}
}
} catch (IOException e) {
this.log(e.getMessage());
} catch (MessagingException e) {
this.log(e.getMessage());
}
}
}
init()可有,可沒有, service() 為必須的, 透過Matcher return collection 後會進入mailet service(), 如果Matcher沒有轉給其他的processor的話,
然後是Matcher的部份,這邊實作的是GenericMatcher , 有另一個為GenericRecipientMatcher ,
GenericMatcher return 為null or mail.getRecipients(), mail.getRecipients()為一個Collection
com.mypackage.matcher.MatcherBySubject
/**
*
*/
package com.mypackage.matcher;
import java.util.Collection;
import javax.mail.MessagingException;
import org.apache.mailet.Mail;
import org.apache.mailet.MailAddress;
import org.apache.mailet.base.GenericMatcher;
import org.apache.mailet.base.GenericRecipientMatcher;
/**
* @author momo
*
*/
public class MatcherBySubject extends GenericMatcher {
@Override
public Collection match(Mail mail) throws MessagingException {
this.log("-->MatcherBySubject start ");
System.out.println("MatcherBySubject return -true");
this.log("getSender =" mail.getSender());
System.out.println("getSender =" mail.getSender());
return null;
}
}
然後打開{yourJamesServerPath}\conf\mailetcontainer.xml, 設定如下
這邊要注意一點,自訂的mailet & matcher設定如下
<mailet match="MatcherBySubject" class="com.mypackage.mailets.FilterByMailet"/>
以上的設定要在 RecipientIsLocal , 這個matcher 的前面,
<mailet match="HostIsLocal" class="ToProcessor">
<processor>local-address-error</processor>
<notice>550 - Requested action not taken: no such user here</notice>
</mailet>
主要是因為Mailet 透過SpoolManager 來控制, SpoolManager 針對processor children 為樹狀模式, 每個processor 都有一個唯一的name屬性, 主要的processor為必要的(如root, error), 而"ghost" 是不可使用的,ghost用來表示不再接受更進一步處理的訊息。James的SpoolManager在processor的名稱和郵件“state”之間創建對應關係。如果狀態改變了,那這個消息就不會繼續留在當前的處理器中。如果為ghost對這個的處理就中止,相對的matcher也可以設定state轉發到另一個processor 。 HostIsLocal的內容如下:
/**
* This mailet redirects the mail to the named processor
*
* Sample configuration:
* <mailet match="All" class="ToProcessor">
* <processor>spam</processor>
* <notice>Notice attached to the message (optional)</notice>
* </mailet>
*
*/
public class ToProcessor extends GenericMailet {
/**
* Controls certain log messages
*/
private boolean isDebug = false;
/**
* The name of the processor to which this mailet forwards mail
*/
String processor;
/**
* The error message to attach to the forwarded message
*/
String noticeText = null;
/**
* Initialize the mailet
*
* @throws MailetException if the processor parameter is missing
*/
public void init() throws MailetException {
isDebug = (getInitParameter("debug") == null) ? false
: new Boolean(getInitParameter("debug")).booleanValue();
processor = getInitParameter("processor");
if (processor == null) {
throw new MailetException("processor parameter is required");
}
noticeText = getInitParameter("notice");
}
/**
* Deliver a mail to the processor.
*
* @param mail the mail to process
*
* @throws MessagingException in all cases
*/
public void service(Mail mail) throws MessagingException {
if (isDebug) {
StringBuffer logBuffer = new StringBuffer(128).append(
"Sending mail ").append(mail).append(" to ")
.append(processor);
log(logBuffer.toString());
}
mail.setState(processor);
if (noticeText != null) {
if (mail.getErrorMessage() == null) {
mail.setErrorMessage(noticeText);
} else {
StringBuffer errorMessageBuffer = new StringBuffer(256)
.append(mail.getErrorMessage()).append("\r\n")
.append(noticeText);
mail.setErrorMessage(errorMessageBuffer.toString());
}
}
}
/**
* Return a string describing this mailet.
*
* @return a string describing this mailet
*/
public String getMailetInfo() {
return "ToProcessor Mailet";
}
}
因為這邊會對自己發信,matcher會match到為local 所以會進入ToProcessor mailet, 在這邊processor = getInitParameter("processor");會設定為local-address-error , 進入service時mail.setState(processor);,這邊就會轉發給local-address-error , 所以我們自訂Mailet 時要注意mailet的位置。
update:
修改Default database from DERBY to MYSQL ,需要mysql-connector-java-5.1.15.jar , 將其放到{yourJamesPath}\conf\lib 下面 ,打開{yourJamesServerPath}\conf\database.properties, 設定如下
然後重啟james server , telnet myhdomain.james 4555 , 重新新增user , James Server 會對db 做create table 的動作。 每一封信寄到James Server時會insert 到database , 當使用者用tools收信時會清除資料。
Update 05/24:
修改smtpserver.xml , 可以透過增加 authorizedAddresses ,讓來源IP 能不需要認證使用mail relay的功能, 新增一個192.168.2.168
<!-- See http://james.apache.org/server/3/config.html for usage -->
<smtpserver enabled="true">
<port>25</port>
<connectionBacklog>200</connectionBacklog>
<tls socketTLS="false" startTLS="false">
</tls>
<handler>
<connectiontimeout>360</connectiontimeout>
<connectionLimit> 0 </connectionLimit>
<connectionLimitPerIP> 0 </connectionLimitPerIP>
<authorizedAddresses>127.0.0.0/8,192.168.2.168</authorizedAddresses>
<authRequired>true</authRequired>
<maxmessagesize>0</maxmessagesize>
<addressBracketsEnforcement>true</addressBracketsEnforcement>
<handlerchain>
<handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
<handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
</handlerchain>
</handler>
</smtpserver>
Reference:
Mailet API Overview
Mailet Container Configuration
Mailets and Matchers Reference
Working with James, Part 1: An introduction to Apache's James enterprise e-mail server
James - Mailet Sample - Omikuji











請問一下~ 關於設定server的部分
回覆刪除為什麼我的{yourJamesServerPath}\conf\裡面沒有mailserver.xml檔呢 !!?
我比對了一下這編在測試用的版本james-server-container-spring-3.0-M2 跟官網現在3.0 的beta版本apache-james-3.0-beta3-app, 新的版本確實是沒有mailserver.xml ,但是在quicstart裡面又有提到mailserver.xml 的檔案(http://james.apache.org/server/3/quick-start.html , 看Step 4: Configure ) 你可以試試看自己建一個mailserver.xml 放上去...@@
回覆刪除我會試試滴~ 謝謝你 ^^
回覆刪除我有測了一下,mailserver.xml 不放的話 照著quick-start 的去啟動,是可以正常啟動mailserver的,可能新版的設定跟我之前用的m2版有些差別吧
回覆刪除再次感謝 >//<
回覆刪除不好意思~ 再請問一下
回覆刪除為什麼我打telnet mydomain.james 4555時會出現下面這種訊息呢?
'telnet' is not recognized as an internal or external command,
operable program or batch file.
我該在哪個目錄下面打這行指令呢?
不好意思~ 我知道囉!! 是win 7把功能鎖調而已 XD
回覆刪除啊,我上週回是用gmail直接回信...忘了他是noreplay的Orz...
回覆刪除不過你有解掉就好了^^
天啊!! 怎麼一直碰到問題..好笨阿我 @@
回覆刪除為什麼我打telnet mydomain.james 4555後會出現下面的錯誤訊息 :
Connecting To mydomain.james...Could not open connection to the host, on port 45
55: Connect failed
這應該是james啟動的時候不認得mydomain.james , 你可以試著用localhost or 127.0.0.1 看行不行, 或著啟動james server後先連看看telnet 127.0.0.1 25試試james server正常啟動了嗎, 新的3.0 beta 的設定還沒去研究過,照我上面的設定應該admin 連的時候會有問題
回覆刪除終於OK囉!!!! 結果我又灌回2.3.2版~ 那個問題就沒有了 ^^
回覆刪除3.0 beta的話還在開發,建議可以等release再用, 不然就要去apache project fourm看討論或問題了, 因為他每次進版會少或多了什麼設定檔也不一定...
回覆刪除如果只是要用mail server的話2.3.x其實還算可用..
只是功能太少,太舊 ..XD
@@ ~~~
回覆刪除Sorry , I didn't update blog for a long time. XDDD