1 | /**** |
---|
2 | * CHANGELOG |
---|
3 | * [12/4/2008 maw] Made it possible to also send attachments with MIME |
---|
4 | * type text/* |
---|
5 | ****/ |
---|
6 | package org.ten60.smtp.accessor; |
---|
7 | |
---|
8 | import com.ten60.netkernel.urii.IURRepresentation; |
---|
9 | import com.ten60.netkernel.urii.aspect.IAspectBinaryStream; |
---|
10 | import org.ten60.netkernel.layer1.util.CompoundURIdentifier; |
---|
11 | import org.ten60.netkernel.xml.representation.IAspectXDA; |
---|
12 | import org.ten60.netkernel.xml.xahelper.XAHelper; |
---|
13 | import org.ten60.netkernel.xml.xahelper.XAHelperExtra; |
---|
14 | import org.ten60.netkernel.xml.xahelper.XAccessor; |
---|
15 | import org.ten60.netkernel.xml.xda.IXDAReadOnly; |
---|
16 | import org.ten60.netkernel.xml.xda.IXDAReadOnlyIterator; |
---|
17 | |
---|
18 | import javax.activation.DataHandler; |
---|
19 | import javax.mail.Message; |
---|
20 | import javax.mail.Session; |
---|
21 | import javax.mail.internet.InternetAddress; |
---|
22 | import javax.mail.internet.MimeBodyPart; |
---|
23 | import javax.mail.internet.MimeMessage; |
---|
24 | import javax.mail.internet.MimeMultipart; |
---|
25 | import java.io.ByteArrayInputStream; |
---|
26 | import java.io.ByteArrayOutputStream; |
---|
27 | import java.net.URI; |
---|
28 | import java.util.HashMap; |
---|
29 | import java.util.Iterator; |
---|
30 | import java.util.Map; |
---|
31 | |
---|
32 | /** |
---|
33 | * Common functionality shared between both the queueing accessor (SMTPAccessor) and |
---|
34 | * the sync accessor (SMTPSyncAccessor). Both extend this class. |
---|
35 | */ |
---|
36 | public abstract class BaseSMTPAccessor extends XAccessor { |
---|
37 | final static String MESSAGE_ARGUMENT = "part"; |
---|
38 | |
---|
39 | protected Session mSession; |
---|
40 | |
---|
41 | protected String mMailAddress; |
---|
42 | protected String mSMTPGateway; |
---|
43 | protected String mSMTPUser; |
---|
44 | protected String mSMTPPassword; |
---|
45 | protected int mSMTPPort=-1; |
---|
46 | |
---|
47 | protected boolean mConfigured = false; |
---|
48 | |
---|
49 | public BaseSMTPAccessor() { |
---|
50 | declareDisableArgumentChecking(); |
---|
51 | } |
---|
52 | |
---|
53 | /** |
---|
54 | * Configure common Email settings |
---|
55 | * |
---|
56 | * @param aHelper The helper class that provides access to the config, |
---|
57 | */ |
---|
58 | protected void configure( XAHelper aHelper ) throws Exception { |
---|
59 | preConfigure(); |
---|
60 | URI configURI = URI.create( "ffcpl:/etc/SMTPConfig.xml" ); |
---|
61 | IURRepresentation rep = aHelper.getResource( configURI, IAspectXDA.class ); |
---|
62 | IAspectXDA config = ( IAspectXDA ) rep.getAspect( IAspectXDA.class ); |
---|
63 | IXDAReadOnly aConfig = config.getXDA(); |
---|
64 | |
---|
65 | mSMTPGateway = aConfig.getText( "/SMTPConfig/SMTPGateway", true ); |
---|
66 | mSMTPUser = aConfig.getText( "/SMTPConfig/SMTPUser", true ); |
---|
67 | mSMTPPassword = aConfig.getText( "/SMTPConfig/SMTPPassword", true ); |
---|
68 | mMailAddress = aConfig.getText( "/SMTPConfig/sender", true ); |
---|
69 | if(aConfig.isTrue("/SMTPConfig/SMTPPort")) |
---|
70 | { mSMTPPort=Integer.parseInt(aConfig.getText("/SMTPConfig/SMTPPort", true)); |
---|
71 | } |
---|
72 | |
---|
73 | //Create mail session |
---|
74 | StringBuffer mailsettings = new StringBuffer( "mail.store.protocol=pop3\n" ); |
---|
75 | mailsettings.append( "mail.transport.protocol=smtp\n" ); |
---|
76 | |
---|
77 | ByteArrayInputStream bis = new ByteArrayInputStream( mailsettings.toString().getBytes() ); |
---|
78 | java.util.Properties ps = new java.util.Properties(); |
---|
79 | ps.load( bis ); |
---|
80 | mSession = Session.getInstance( ps ); |
---|
81 | mConfigured = true; |
---|
82 | postConfigure(); |
---|
83 | } |
---|
84 | |
---|
85 | /** |
---|
86 | * Abstract method to be implemented in subclass. |
---|
87 | * |
---|
88 | * @param aHelper The helper class that provides access to the operator, |
---|
89 | * operand, and parameters. |
---|
90 | * @return Either the result as a Document or a Reader. |
---|
91 | */ |
---|
92 | public IURRepresentation source( XAHelper aHelper ) throws Exception { |
---|
93 | Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() ); |
---|
94 | if( !mConfigured || ( aHelper.hasOperator() && aHelper.getOperator().getXDA().isTrue( "/reconfigure" ) ) ) { |
---|
95 | configure( aHelper ); |
---|
96 | } |
---|
97 | if( !aHelper.hasOperator() ) { |
---|
98 | IXDAReadOnly opd = aHelper.getOperand().getXDA(); |
---|
99 | |
---|
100 | MimeMessage message = new MimeMessage( mSession ); |
---|
101 | message.setSubject( opd.getText( "/email/subject", true ) ); |
---|
102 | String from = null; |
---|
103 | if( opd.isTrue( "/email/from" ) ) { |
---|
104 | from = opd.getText( "/email/from", true ); |
---|
105 | } else from = mMailAddress; |
---|
106 | InternetAddress IAfrom = new InternetAddress( from ); |
---|
107 | message.setSender( IAfrom ); |
---|
108 | message.setFrom( IAfrom ); |
---|
109 | |
---|
110 | IXDAReadOnlyIterator ir = opd.readOnlyIterator( "/email/to" ); |
---|
111 | Map map = new HashMap( 5 ); |
---|
112 | while( ir.hasNext() ) { |
---|
113 | ir.next(); |
---|
114 | String to = ir.getText( ".", true ); |
---|
115 | if( !map.containsKey( to ) ) { |
---|
116 | message.addRecipient( Message.RecipientType.TO, new InternetAddress( to ) ); |
---|
117 | map.put( to, Boolean.TRUE ); |
---|
118 | } |
---|
119 | } |
---|
120 | |
---|
121 | ir = opd.readOnlyIterator( "/email/cc" ); |
---|
122 | map = new HashMap( 5 ); |
---|
123 | while( ir.hasNext() ) { |
---|
124 | ir.next(); |
---|
125 | String cc = ir.getText( ".", true ); |
---|
126 | if( !map.containsKey( cc ) ) { |
---|
127 | message.addRecipient( Message.RecipientType.CC, new InternetAddress( cc ) ); |
---|
128 | map.put( cc, Boolean.TRUE ); |
---|
129 | } |
---|
130 | } |
---|
131 | ir = opd.readOnlyIterator( "/email/bcc" ); |
---|
132 | map = new HashMap( 5 ); |
---|
133 | while( ir.hasNext() ) { |
---|
134 | ir.next(); |
---|
135 | String bcc = ir.getText( ".", true ); |
---|
136 | if( !map.containsKey( bcc ) ) { |
---|
137 | message.addRecipient( Message.RecipientType.BCC, new InternetAddress( bcc ) ); |
---|
138 | map.put( bcc, Boolean.TRUE ); |
---|
139 | } |
---|
140 | } |
---|
141 | |
---|
142 | //Add Messages |
---|
143 | MimeMultipart replymp = new MimeMultipart(); |
---|
144 | XAHelperExtra extra = ( XAHelperExtra ) aHelper; |
---|
145 | CompoundURIdentifier curi = new CompoundURIdentifier( extra.getRequest().getURI() ); |
---|
146 | Iterator i = curi.getArgs(); |
---|
147 | boolean messageflag = false; |
---|
148 | while( i.hasNext() ) { |
---|
149 | CompoundURIdentifier.CompoundURIStruct struct = ( CompoundURIdentifier.CompoundURIStruct ) i.next(); |
---|
150 | if( !struct.getKey().equals( "operand" ) ) { |
---|
151 | messageflag = true; |
---|
152 | IURRepresentation rep = aHelper.getResource( URI.create( struct.getURI() ), IAspectBinaryStream.class ); |
---|
153 | IAspectBinaryStream bsAspect = ( IAspectBinaryStream ) rep.getAspect( IAspectBinaryStream.class ); |
---|
154 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
---|
155 | bsAspect.write( baos ); |
---|
156 | baos.flush(); |
---|
157 | MimeBodyPart mbp = new MimeBodyPart(); |
---|
158 | DataHandler dh = null; |
---|
159 | if( !rep.getMeta().getMimeType().startsWith( "text" ) || aHelper.getOperand().getXDA().isTrue( "//attachment[name='" + struct.getKey() + "']") ) { |
---|
160 | System.err.println("DBG: "+struct.getKey()+":handled as attachment"); |
---|
161 | ByteArrayDataSource bads = new ByteArrayDataSource( baos.toByteArray(), rep.getMeta().getMimeType() ); |
---|
162 | dh = new DataHandler( bads ); |
---|
163 | try { |
---|
164 | mbp.setFileName( aHelper.getOperand().getXDA().getText( "//attachment[name='" + struct.getKey() + "']/filename", true ) ); |
---|
165 | } |
---|
166 | catch( Exception e ) { |
---|
167 | mbp.setFileName( struct.getKey() ); |
---|
168 | } |
---|
169 | } else { |
---|
170 | System.err.println("DBG: "+struct.getKey()+":handled as part"); |
---|
171 | dh = new DataHandler( baos.toString(), rep.getMeta().getMimeType() ); |
---|
172 | } |
---|
173 | mbp.setDataHandler( dh ); |
---|
174 | replymp.addBodyPart( mbp ); |
---|
175 | } |
---|
176 | } |
---|
177 | if( !messageflag ) throw new Exception( "Must provide at least one message part argument" ); |
---|
178 | message.setContent( replymp ); |
---|
179 | message.saveChanges(); |
---|
180 | |
---|
181 | messageAction( message ); |
---|
182 | } |
---|
183 | return org.ten60.netkernel.layer1.representation.VoidAspect.create(); |
---|
184 | } |
---|
185 | |
---|
186 | protected abstract void preConfigure() throws Exception; |
---|
187 | |
---|
188 | protected abstract void postConfigure() throws Exception; |
---|
189 | |
---|
190 | protected abstract void messageAction( MimeMessage message ) throws Exception; |
---|
191 | |
---|
192 | } |
---|