Apache James + Groovy でメール連携アプリケーション その1



ちょっと時間ができたので、Java製メールサーバJamesとGroovyで
メールを受信した時に何か応答するアプリケーションを作ってみます.

以前の記事にも書いたのですが、この組み合わせの理由は、
「jarに固めて、サーバに配置して、James再起動」
という開発は面倒くさそうだから、デバックが必要な部分を
Groovyで記述してしまえばいいのでは?と思ったからです.

JavaとGroovyの連携は以前調べていたので・・・
http://fujishinko.exblog.jp/7216773

これを応用して、JamesからGroovyのスクリプトが呼べるようにします。

■MainProcess.java

package jp.dip.dkdc.james;

import javax.mail.*;
import javax.mail.internet.*;
import org.apache.avalon.cornerstone.services.datasources.DataSourceSelector;
import org.apache.avalon.excalibur.datasource.DataSourceComponent;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.james.Constants;
import org.apache.mailet.Mail;
import org.apache.mailet.GenericMailet;
import org.apache.mailet.MailetContext;
import java.sql.*;
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;

//Jamesがメールを受信した時に呼ばれるクラス
public class MainProcess extends GenericMailet{
    //DBコネクションプール
    private DataSourceComponent dsc;
    //Groovyスクリプト実行
    private GroovyScriptEngine gse;
    //実行するスクリプト名
    private String script;
    
    public void init() throws MessagingException {
    
        try {
            DefaultServiceManager dsm = (DefaultServiceManager) getMailetContext().getAttribute(Constants.AVALON_COMPONENT_MANAGER);
            DataSourceSelector dss = (DataSourceSelector) dsm.lookup(DataSourceSelector.ROLE);
            dsc = (DataSourceComponent) dss.select("dkdc");
        } catch (Exception e){
            throw new MessagingException("DB接続初期化エラー", e );
        }
        
        try {
            gse = new GroovyScriptEngine("/var/local/james/");
        } catch (Exception e){
            throw new MessagingException("GroovyScriptEngine初期化エラー", e);
        }

        script = getInitParameter("script");
        if (script == null) {
            throw new MessagingException("スクリプトファイル名取得エラー");
        }
    }

    //メール受診時の動作
    //Groovyスクリプトを実行する
    public void service(Mail arg0) throws MessagingException {
        Binding binding = new Binding();
        Connection con = null;
        
        try {
            
            con = dsc.getConnection();
            
            MailData data = new MailData(arg0);
            
            System.out.println(data.getSender());
            
            //自分宛のメールは処理しない
            if (data.getSender().equals("a@exmple.com")) {
                return;
            }
            
            binding.setVariable("mail",data);
            binding.setVariable("db", con);
            
            //スクリプト呼び出し
            MailData result = (MailData)gse.run(script, binding);
            
            //結果を送信
            if (result != null) {
                MimeMessage mm = new MimeMessage((Session)null);
                
                mm.setHeader("Content-Transfer-Encoding", "7bit");
                mm.setSubject(result.getSubject(),"ISO-2022-JP");
                mm.setText(result.getBody(), "ISO-2022-JP");
                mm.setFrom(new InternetAddress("a@dkdc.dip.jp"));
                mm.setSentDate(new java.util.Date());
                mm.setRecipient(Message.RecipientType.TO,new InternetAddress(result.getSender()));

                //送信
                MailetContext mc = getMailetContext();
                mc.sendMail(mm);
                
            }    
        } catch(Exception e){
            throw new MessagingException("", e);
        } finally {
            try {
                if (con != null) {
                    con.close();
                }
            } catch (Exception ex){}
        }
    }
}



■MailData.java

package jp.dip.dkdc.james;

import java.io.IOException;

import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;

import org.apache.mailet.*;

//メールデータ保持クラス
public class MailData {

    //送信者
    private String sender = "";
    //件名
    private String subject = "";
    //本文
    private String body = "";


    public MailData() {
    }

    //Jamesで受信したメールのパースを実行
    public MailData(Mail mail) throws MessagingException {
        MailAddress addr = mail.getSender();
        sender = addr.toString();
        try {
            MimeMessage message = mail.getMessage();
            subject = message.getSubject();
            body = getText(message);
        } catch(Exception e){
            subject = "";
            body = "";
            throw new MessagingException("メールパースエラー", e);
        }
    }

    public String getBody() {
        return body;
    }
    public void setBody(String body) {
        this.body = body;
    }
    public String getSender() {
        return sender;
    }
    public void setSender(String sender) {
        this.sender = sender;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String title) {
        this.subject = title;
    }

    // MimeMessage解析
    private String getText( MimePart part ) throws MessagingException, IOException {
        // Mime Type により分岐
        if( part.isMimeType( "text/plain" ) ) {
            return part.getContent().toString();
        } else if( part.isMimeType( "text/html" ) ) {
            return part.getContent().toString();
        } else if( part.isMimeType( "multipart/mixed" ) ) {
            MimeMultipart mp = (MimeMultipart)part.getContent();
            return mp.getBodyPart(0).getContent().toString();
        } else if( part.isMimeType( "multipart/alternative" ) ){
            MimeMultipart mp = (MimeMultipart)part.getContent();
            int num = mp.getCount();
            for( int i = 0; i < num; i++ ) {
                MimeBodyPart body = (MimeBodyPart)mp.getBodyPart(i);
                String ret = getText( body );
                if( ret != null ) {
                    return ret;
                }
            }
            return null;
        } else {
            return null;
        }
    }
}



もどる