Source Code Cross Referenced for DSNBounce.java in  » Net » james-2.3.1 » org » apache » james » transport » mailets » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » james 2.3.1 » org.apache.james.transport.mailets 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /****************************************************************
002:         * Licensed to the Apache Software Foundation (ASF) under one   *
003:         * or more contributor license agreements.  See the NOTICE file *
004:         * distributed with this work for additional information        *
005:         * regarding copyright ownership.  The ASF licenses this file   *
006:         * to you under the Apache License, Version 2.0 (the            *
007:         * "License"); you may not use this file except in compliance   *
008:         * with the License.  You may obtain a copy of the License at   *
009:         *                                                              *
010:         *   http://www.apache.org/licenses/LICENSE-2.0                 *
011:         *                                                              *
012:         * Unless required by applicable law or agreed to in writing,   *
013:         * software distributed under the License is distributed on an  *
014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015:         * KIND, either express or implied.  See the License for the    *
016:         * specific language governing permissions and limitations      *
017:         * under the License.                                           *
018:         ****************************************************************/package org.apache.james.transport.mailets;
019:
020:        import org.apache.james.Constants;
021:        import org.apache.james.core.MailImpl;
022:        import org.apache.james.util.mail.MimeMultipartReport;
023:        import org.apache.james.util.mail.dsn.DSNStatus;
024:        import org.apache.mailet.Mail;
025:        import org.apache.mailet.MailAddress;
026:        import org.apache.mailet.RFC2822Headers;
027:        import org.apache.mailet.dates.RFC822DateFormat;
028:        import org.apache.oro.text.regex.MalformedPatternException;
029:        import org.apache.oro.text.regex.MatchResult;
030:        import org.apache.oro.text.regex.Pattern;
031:        import org.apache.oro.text.regex.Perl5Compiler;
032:        import org.apache.oro.text.regex.Perl5Matcher;
033:
034:        import javax.mail.MessagingException;
035:        import javax.mail.SendFailedException;
036:        import javax.mail.Session;
037:        import javax.mail.internet.InternetAddress;
038:        import javax.mail.internet.MimeBodyPart;
039:        import javax.mail.internet.MimeMessage;
040:
041:        import java.io.PrintWriter;
042:        import java.io.StringWriter;
043:        import java.net.ConnectException;
044:        import java.net.InetAddress;
045:        import java.net.SocketException;
046:        import java.net.UnknownHostException;
047:        import java.util.Collection;
048:        import java.util.Date;
049:        import java.util.HashSet;
050:        import java.util.Iterator;
051:
052:        /**
053:         *
054:         * <P>Generates a Delivery Status Notification (DSN)
055:         * Note that this is different than a mail-client's
056:         * reply, which would use the Reply-To or From header.</P>
057:         * <P>Bounced messages are attached in their entirety (headers and
058:         * content) and the resulting MIME part type is "message/rfc822".<BR>
059:         * The reverse-path and the Return-Path header of the response is set to "null" ("<>"),
060:         * meaning that no reply should be sent.</P>
061:         * <P>A sender of the notification message can optionally be specified.
062:         * If one is not specified, the postmaster's address will be used.<BR>
063:         * <P>Supports the <CODE>passThrough</CODE> init parameter (true if missing).</P>
064:         *
065:         * <P>Sample configuration:</P>
066:         * <PRE><CODE>
067:         * &lt;mailet match="All" class="DSNBounce">
068:         *   &lt;sender&gt;<I>an address or postmaster or sender or unaltered, 
069:         default=postmaster</I>&lt;/sender&gt;
070:         *   &lt;prefix&gt;<I>optional subject prefix prepended to the original 
071:         message</I>&lt;/prefix&gt;
072:         *   &lt;attachment&gt;<I>message, heads or none, default=message</I>&lt;/attachment&gt;
073:         *   &lt;messageString&gt;<I>the message sent in the bounce, the first occurrence of the pattern [machine] is replaced with the name of the executing machine, default=Hi. This is the James mail server at [machine] ... </I>&lt;/messageString&gt;
074:         *   &lt;passThrough&gt;<I>true or false, default=true</I>&lt;/passThrough&gt;
075:         *   &lt;debug&gt;<I>true or false, default=false</I>&lt;/debug&gt;
076:         * &lt;/mailet&gt;
077:         * </CODE></PRE>
078:         *
079:         * @see org.apache.james.transport.mailets.AbstractNotify
080:         */
081:
082:        public class DSNBounce extends AbstractNotify {
083:
084:            private static final RFC822DateFormat rfc822DateFormat = new RFC822DateFormat();
085:
086:            //  Used to generate new mail names
087:            private static final java.util.Random random = new java.util.Random();
088:
089:            // regexp pattern for scaning status code from exception message
090:            private static Pattern statusPattern;
091:
092:            private static Pattern diagPattern;
093:
094:            private static final String MACHINE_PATTERN = "[machine]";
095:
096:            private String messageString = null;
097:
098:            /*
099:             * Static initializer.<p>
100:             * Compiles patterns for processing exception messages.<p>
101:             */
102:            static {
103:                Perl5Compiler compiler = new Perl5Compiler();
104:                String status_pattern_string = ".*\\s*([245]\\.\\d{1,3}\\.\\d{1,3}).*\\s*";
105:                String diag_pattern_string = "^\\d{3}\\s.*$";
106:                try {
107:                    statusPattern = compiler.compile(status_pattern_string,
108:                            Perl5Compiler.READ_ONLY_MASK);
109:                } catch (MalformedPatternException mpe) {
110:                    //this should not happen as the pattern string is hardcoded.
111:                    System.err.println("Malformed pattern: "
112:                            + status_pattern_string);
113:                    mpe.printStackTrace(System.err);
114:                }
115:                try {
116:                    diagPattern = compiler.compile(diag_pattern_string,
117:                            Perl5Compiler.READ_ONLY_MASK);
118:                } catch (MalformedPatternException mpe) {
119:                    //this should not happen as the pattern string is hardcoded.
120:                    System.err.println("Malformed pattern: "
121:                            + diag_pattern_string);
122:                }
123:            }
124:
125:            /**
126:             * Initialize the mailet
127:             */
128:            public void init() throws MessagingException {
129:                super .init();
130:                messageString = getInitParameter(
131:                        "messageString",
132:                        "Hi. This is the James mail server at [machine].\nI'm afraid I wasn't able to deliver your message to the following addresses.\nThis is a permanent error; I've given up. Sorry it didn't work out.  Below\nI include the list of recipients and the reason why I was unable to deliver\nyour message.\n");
133:            }
134:
135:            /**
136:             * Service does the hard work and bounces the originalMail in the format specified by RFC3464.
137:             *
138:             * @param originalMail the mail to bounce
139:             * @throws MessagingException if a problem arises formulating the redirected mail
140:             *
141:             * @see org.apache.mailet.Mailet#service(org.apache.mailet.Mail)
142:             */
143:            public void service(Mail originalMail) throws MessagingException {
144:
145:                // duplicates the Mail object, to be able to modify the new mail keeping the original untouched
146:                MailImpl newMail = new MailImpl(originalMail,
147:                        newName(originalMail));
148:                try {
149:                    // We don't need to use the original Remote Address and Host,
150:                    // and doing so would likely cause a loop with spam detecting
151:                    // matchers.
152:                    try {
153:                        newMail.setRemoteAddr(java.net.InetAddress
154:                                .getLocalHost().getHostAddress());
155:                        newMail.setRemoteHost(java.net.InetAddress
156:                                .getLocalHost().getHostName());
157:                    } catch (java.net.UnknownHostException _) {
158:                        newMail.setRemoteAddr("127.0.0.1");
159:                        newMail.setRemoteHost("localhost");
160:                    }
161:
162:                    if (originalMail.getSender() == null) {
163:                        if (isDebug)
164:                            log("Processing a bounce request for a message with an empty reverse-path.  No bounce will be sent.");
165:                        if (!getPassThrough(originalMail)) {
166:                            originalMail.setState(Mail.GHOST);
167:                        }
168:                        return;
169:                    }
170:
171:                    MailAddress reversePath = originalMail.getSender();
172:                    if (isDebug)
173:                        log("Processing a bounce request for a message with a reverse path.  The bounce will be sent to "
174:                                + reversePath);
175:
176:                    Collection newRecipients = new HashSet();
177:                    newRecipients.add(reversePath);
178:                    newMail.setRecipients(newRecipients);
179:
180:                    if (isDebug) {
181:                        log("New mail - sender: "
182:                                + newMail.getSender()
183:                                + ", recipients: "
184:                                + arrayToString(newMail.getRecipients()
185:                                        .toArray()) + ", name: "
186:                                + newMail.getName() + ", remoteHost: "
187:                                + newMail.getRemoteHost() + ", remoteAddr: "
188:                                + newMail.getRemoteAddr() + ", state: "
189:                                + newMail.getState() + ", lastUpdated: "
190:                                + newMail.getLastUpdated() + ", errorMessage: "
191:                                + newMail.getErrorMessage());
192:                    }
193:
194:                    // create the bounce message
195:                    MimeMessage newMessage = new MimeMessage(Session
196:                            .getDefaultInstance(System.getProperties(), null));
197:
198:                    MimeMultipartReport multipart = new MimeMultipartReport();
199:                    multipart.setReportType("delivery-status");
200:
201:                    // part 1: descripive text message
202:                    MimeBodyPart part1 = createTextMsg(originalMail);
203:                    multipart.addBodyPart(part1);
204:
205:                    // part 2: DSN
206:                    MimeBodyPart part2 = createDSN(originalMail);
207:                    multipart.addBodyPart(part2);
208:
209:                    // part 3: original mail (optional)
210:                    if (getAttachmentType() != NONE) {
211:                        MimeBodyPart part3 = createAttachedOriginal(
212:                                originalMail, getAttachmentType());
213:                        multipart.addBodyPart(part3);
214:                    }
215:
216:                    // stuffing all together
217:                    newMessage.setContent(multipart);
218:                    newMessage.setHeader(RFC2822Headers.CONTENT_TYPE, multipart
219:                            .getContentType());
220:                    newMail.setMessage(newMessage);
221:
222:                    //Set additional headers
223:                    setRecipients(newMail, getRecipients(originalMail),
224:                            originalMail);
225:                    setTo(newMail, getTo(originalMail), originalMail);
226:                    setSubjectPrefix(newMail, getSubjectPrefix(originalMail),
227:                            originalMail);
228:                    if (newMail.getMessage().getHeader(RFC2822Headers.DATE) == null) {
229:                        newMail.getMessage().setHeader(RFC2822Headers.DATE,
230:                                rfc822DateFormat.format(new Date()));
231:                    }
232:                    setReplyTo(newMail, getReplyTo(originalMail), originalMail);
233:                    setReversePath(newMail, getReversePath(originalMail),
234:                            originalMail);
235:                    setSender(newMail, getSender(originalMail), originalMail);
236:                    setIsReply(newMail, isReply(originalMail), originalMail);
237:
238:                    newMail.getMessage().saveChanges();
239:                    getMailetContext().sendMail(newMail);
240:                } finally {
241:                    newMail.dispose();
242:                }
243:
244:                // ghosting the original mail
245:                if (!getPassThrough(originalMail)) {
246:                    originalMail.setState(Mail.GHOST);
247:                }
248:            }
249:
250:            /**
251:             * Create a MimeBodyPart with a textual description for human readers.
252:             *
253:             * @param originalMail
254:             * @return MimeBodyPart
255:             * @throws MessagingException
256:             */
257:            protected MimeBodyPart createTextMsg(Mail originalMail)
258:                    throws MessagingException {
259:                MimeBodyPart part1 = new MimeBodyPart();
260:                StringWriter sout = new StringWriter();
261:                PrintWriter out = new PrintWriter(sout, true);
262:                String machine = "[unknown]";
263:                try {
264:                    InetAddress me = InetAddress.getLocalHost();
265:                    machine = me.getHostName();
266:                } catch (Exception e) {
267:                    machine = "[address unknown]";
268:                }
269:
270:                StringBuffer bounceBuffer = new StringBuffer(128)
271:                        .append(messageString);
272:                int m_idx_begin = messageString.indexOf(MACHINE_PATTERN);
273:                if (m_idx_begin != -1) {
274:                    bounceBuffer.replace(m_idx_begin, m_idx_begin
275:                            + MACHINE_PATTERN.length(), machine);
276:                }
277:                out.println(bounceBuffer.toString());
278:                out.println("Failed recipient(s):");
279:                for (Iterator i = originalMail.getRecipients().iterator(); i
280:                        .hasNext();) {
281:                    out.println(i.next());
282:                }
283:                MessagingException ex = (MessagingException) originalMail
284:                        .getAttribute("delivery-error");
285:                out.println();
286:                out.println("Error message:");
287:                out.println(getErrorMsg(ex));
288:                out.println();
289:
290:                part1.setText(sout.toString());
291:                return part1;
292:            }
293:
294:            /**
295:             * creates the DSN-bodypart for automated processing
296:             *
297:             * @param originalMail
298:             * @return MimeBodyPart dsn-bodypart
299:             * @throws MessagingException
300:             */
301:            protected MimeBodyPart createDSN(Mail originalMail)
302:                    throws MessagingException {
303:                MimeBodyPart dsn = new MimeBodyPart();
304:                StringWriter sout = new StringWriter();
305:                PrintWriter out = new PrintWriter(sout, true);
306:                String nameType = null;
307:
308:                ////////////////////////
309:                // per message fields //
310:                ////////////////////////
311:
312:                //optional: envelope-id
313:                // TODO: Envelope-Id
314:                // The Original-Envelope-Id is NOT the same as the Message-Id from the header.
315:                // The Message-Id identifies the content of the message, while the Original-Envelope-ID
316:                // identifies the transaction in which the message is sent.  (see RFC3461)
317:                // so do NOT out.println("Original-Envelope-Id:"+originalMail.getMessage().getMessageID());
318:
319:                //required: reporting MTA
320:                // this is always us, since we do not translate non-internet-mail
321:                // failure reports into DSNs
322:                nameType = "dns";
323:                try {
324:                    String myAddress = (String) getMailetContext()
325:                            .getAttribute(Constants.HELLO_NAME);
326:                    /*
327:                    String myAddress = InetAddress.getLocalHost().getCanonicalHostName();
328:                     */
329:                    out
330:                            .println("Reporting-MTA: " + nameType + "; "
331:                                    + myAddress);
332:                } catch (Exception e) {
333:                    // we should always know our address, so we shouldn't get here
334:                    log("WARNING: sending DSN without required Reporting-MTA Address");
335:                }
336:
337:                //only for gateways to non-internet mail systems: dsn-gateway
338:
339:                //optional: received from
340:                out.println("Received-From-MTA: " + nameType + "; "
341:                        + originalMail.getRemoteHost());
342:
343:                //optional: Arrival-Date
344:
345:                //////////////////////////
346:                // per recipient fields //
347:                //////////////////////////
348:
349:                Iterator recipients = originalMail.getRecipients().iterator();
350:                while (recipients.hasNext()) {
351:                    MailAddress rec = (MailAddress) recipients.next();
352:                    String addressType = "rfc822";
353:
354:                    //required: blank line
355:                    out.println();
356:
357:                    //optional: original recipient (see RFC3461)
358:                    //out.println("Original-Recipient: "+addressType+"; "+ ??? );
359:
360:                    //required: final recipient
361:                    out.println("Final-Recipient: " + addressType + "; "
362:                            + rec.toString());
363:
364:                    //required: action
365:                    // alowed values: failed, delayed, delivered, relayed, expanded
366:                    // TODO: until now, we do error-bounces only
367:                    out.println("Action: failed");
368:
369:                    //required: status
370:                    // get Exception for getting status information
371:                    // TODO: it would be nice if the SMTP-handler would set a status attribute we can use here
372:                    MessagingException ex = (MessagingException) originalMail
373:                            .getAttribute("delivery-error");
374:                    out.println("Status: " + getStatus(ex));
375:
376:                    //optional: remote MTA
377:                    //to which MTA were we talking while the Error occured?
378:
379:                    //optional: diagnostic-code
380:                    String diagnosticType = null;
381:                    // this typically is the return value received during smtp
382:                    // (or other transport) communication
383:                    // and should be stored as attribute by the smtp handler
384:                    // but until now we only have error-messages.
385:                    String diagnosticCode = getErrorMsg(ex);
386:                    // Sometimes this is the smtp diagnostic code,
387:                    // but James often gives us other messages
388:                    Perl5Matcher diagMatcher = new Perl5Matcher();
389:                    boolean smtpDiagCodeAvailable = diagMatcher.matches(
390:                            diagnosticCode, diagPattern);
391:                    if (smtpDiagCodeAvailable) {
392:                        diagnosticType = "smtp";
393:                    } else {
394:                        diagnosticType = "X-James";
395:                    }
396:                    out.println("Diagnostic-Code: " + diagnosticType + "; "
397:                            + diagnosticCode);
398:
399:                    //optional: last attempt
400:                    out.println("Last-Attempt-Date: "
401:                            + rfc822DateFormat.format(originalMail
402:                                    .getLastUpdated()));
403:
404:                    //optional: retry until
405:                    //only for 'delayed' reports .. but we don't report this (at least until now)
406:
407:                    //optional: extension fields
408:
409:                }
410:
411:                // Changed this from rfc822 handling to text/plain
412:                // It should be handled correctly as delivery-status but it
413:                // is better text/plain than rfc822 (rfc822 add message headers not
414:                // allowed in the delivery-status.
415:                // text/plain does not support rfc822 header encoding that we
416:                // should support here.
417:                dsn.setContent(sout.toString(), "text/plain");
418:                dsn.setHeader("Content-Type", "message/delivery-status");
419:                dsn.setDescription("Delivery Status Notification");
420:                dsn.setFileName("status.dat");
421:                return dsn;
422:            }
423:
424:            /**
425:             * Create a MimeBodyPart with the original Mail as Attachment
426:             *
427:             * @param originalMail
428:             * @return MimeBodyPart
429:             * @throws MessagingException
430:             */
431:            protected MimeBodyPart createAttachedOriginal(Mail originalMail,
432:                    int attachmentType) throws MessagingException {
433:                MimeBodyPart part = new MimeBodyPart();
434:                MimeMessage originalMessage = originalMail.getMessage();
435:
436:                if (attachmentType == HEADS) {
437:                    part.setContent(getMessageHeaders(originalMessage),
438:                            "text/plain");
439:                    part.setHeader("Content-Type", "text/rfc822-headers");
440:                } else {
441:                    part.setContent(originalMessage, "message/rfc822");
442:                }
443:
444:                if ((originalMessage.getSubject() != null)
445:                        && (originalMessage.getSubject().trim().length() > 0)) {
446:                    part.setFileName(originalMessage.getSubject().trim());
447:                } else {
448:                    part.setFileName("No Subject");
449:                }
450:                part.setDisposition("Attachment");
451:                return part;
452:            }
453:
454:            /**
455:             * Guessing status code by the exception provided.
456:             * This method should use the status attribute when the
457:             * SMTP-handler somewhen provides it
458:             *
459:             * @param MessagingException
460:             * @return status code
461:             */
462:            protected String getStatus(MessagingException me) {
463:                if (me.getNextException() == null) {
464:                    String mess = me.getMessage();
465:                    Perl5Matcher m = new Perl5Matcher();
466:                    StringBuffer sb = new StringBuffer();
467:                    if (m.matches(mess, statusPattern)) {
468:                        MatchResult res = m.getMatch();
469:                        sb.append(res.group(1));
470:                        return sb.toString();
471:                    }
472:                    // bad destination system adress
473:                    if (mess
474:                            .startsWith("There are no DNS entries for the hostname"))
475:                        return DSNStatus.getStatus(DSNStatus.PERMANENT,
476:                                DSNStatus.ADDRESS_SYSTEM);
477:
478:                    // no answer from host (4.4.1) or
479:                    // system not accepting network messages (4.3.2), lets guess ...
480:                    if (mess
481:                            .equals("No mail server(s) available at this time."))
482:                        return DSNStatus.getStatus(DSNStatus.TRANSIENT,
483:                                DSNStatus.NETWORK_NO_ANSWER);
484:
485:                    // other/unknown error
486:                    return DSNStatus.getStatus(DSNStatus.PERMANENT,
487:                            DSNStatus.UNDEFINED_STATUS);
488:                } else {
489:                    Exception ex1 = me.getNextException();
490:                    Perl5Matcher m = new Perl5Matcher();
491:                    StringBuffer sb = new StringBuffer();
492:                    if (m.matches(ex1.getMessage(), statusPattern)) {
493:                        MatchResult res = m.getMatch();
494:                        sb.append(res.group(1));
495:                        return sb.toString();
496:                    } else if (ex1 instanceof  SendFailedException) {
497:                        // other/undefined protocol status
498:                        int smtpCode = 0;
499:                        try {
500:                            smtpCode = Integer.parseInt(ex1.getMessage()
501:                                    .substring(0, 3));
502:                        } catch (NumberFormatException e) {
503:                        }
504:
505:                        switch (smtpCode) {
506:
507:                        // Req mail action not taken: mailbox unavailable
508:                        case 450:
509:                            return DSNStatus.getStatus(DSNStatus.TRANSIENT,
510:                                    DSNStatus.MAILBOX_OTHER);
511:                            // Req action aborted: local error in processing
512:                        case 451:
513:                            return DSNStatus.getStatus(DSNStatus.TRANSIENT,
514:                                    DSNStatus.SYSTEM_OTHER);
515:                            // Req action not taken: insufficient sys storage
516:                        case 452:
517:                            return DSNStatus.getStatus(DSNStatus.TRANSIENT,
518:                                    DSNStatus.SYSTEM_FULL);
519:                            // Syntax error, command unrecognized
520:                        case 500:
521:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
522:                                    DSNStatus.DELIVERY_SYNTAX);
523:                            // Syntax error in parameters or arguments
524:                        case 501:
525:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
526:                                    DSNStatus.DELIVERY_INVALID_ARG);
527:                            // Command not implemented
528:                        case 502:
529:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
530:                                    DSNStatus.DELIVERY_INVALID_CMD);
531:                            // Bad sequence of commands
532:                        case 503:
533:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
534:                                    DSNStatus.DELIVERY_INVALID_CMD);
535:                            // Command parameter not implemented
536:                        case 504:
537:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
538:                                    DSNStatus.DELIVERY_INVALID_ARG);
539:                            // Req mail action not taken: mailbox unavailable
540:                        case 550:
541:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
542:                                    DSNStatus.MAILBOX_OTHER);
543:                            // User not local; please try <...>
544:                            // 5.7.1 Select another host to act as your forwarder
545:                        case 551:
546:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
547:                                    DSNStatus.SECURITY_AUTH);
548:                            // Req mail action aborted: exceeded storage alloc
549:                        case 552:
550:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
551:                                    DSNStatus.MAILBOX_FULL);
552:                            // Req action not taken: mailbox name not allowed
553:                        case 553:
554:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
555:                                    DSNStatus.ADDRESS_SYNTAX);
556:                            // Transaction failed
557:                        case 554:
558:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
559:                                    DSNStatus.UNDEFINED_STATUS);
560:                            // Not authorized. This is not an SMTP code, but many server use it.
561:                        case 571:
562:                            return DSNStatus.getStatus(DSNStatus.PERMANENT,
563:                                    DSNStatus.SECURITY_AUTH);
564:
565:                        default:
566:                            // if we get an smtp returncode starting with 4
567:                            // it is an persistent transient error, else permanent
568:                            if (ex1.getMessage().startsWith("4")) {
569:                                return DSNStatus.getStatus(DSNStatus.TRANSIENT,
570:                                        DSNStatus.DELIVERY_OTHER);
571:                            } else
572:                                return DSNStatus.getStatus(DSNStatus.PERMANENT,
573:                                        DSNStatus.DELIVERY_OTHER);
574:                        }
575:
576:                    } else if (ex1 instanceof  UnknownHostException) {
577:                        // bad destination system address
578:                        return DSNStatus.getStatus(DSNStatus.PERMANENT,
579:                                DSNStatus.ADDRESS_SYSTEM);
580:                    } else if (ex1 instanceof  ConnectException) {
581:                        // bad connection
582:                        return DSNStatus.getStatus(DSNStatus.TRANSIENT,
583:                                DSNStatus.NETWORK_CONNECTION);
584:                    } else if (ex1 instanceof  SocketException) {
585:                        // bad connection
586:                        return DSNStatus.getStatus(DSNStatus.TRANSIENT,
587:                                DSNStatus.NETWORK_CONNECTION);
588:                    } else {
589:                        // other/undefined/unknown error
590:                        return DSNStatus.getStatus(DSNStatus.PERMANENT,
591:                                DSNStatus.UNDEFINED_STATUS);
592:                    }
593:                }
594:            }
595:
596:            /**
597:             * Utility method for getting the error message from the (nested) exception.
598:             * @param MessagingException
599:             * @return error message
600:             */
601:            protected String getErrorMsg(MessagingException me) {
602:                if (me.getNextException() == null) {
603:                    return me.getMessage().trim();
604:                } else {
605:                    Exception ex1 = me.getNextException();
606:                    return ex1.getMessage().trim();
607:                }
608:            }
609:
610:            /**
611:             * Utility method for obtaining a string representation of an array of Objects.
612:             */
613:            private String arrayToString(Object[] array) {
614:                if (array == null) {
615:                    return "null";
616:                }
617:                StringBuffer sb = new StringBuffer(1024);
618:                sb.append("[");
619:                for (int i = 0; i < array.length; i++) {
620:                    if (i > 0) {
621:                        sb.append(",");
622:                    }
623:                    sb.append(array[i]);
624:                }
625:                sb.append("]");
626:                return sb.toString();
627:            }
628:
629:            /**
630:             * Create a unique new primary key name.
631:             *
632:             * @param mail the mail to use as the basis for the new mail name
633:             * @return a new name
634:             */
635:            protected String newName(Mail mail) throws MessagingException {
636:                String oldName = mail.getName();
637:
638:                // Checking if the original mail name is too long, perhaps because of a
639:                // loop caused by a configuration error.
640:                // it could cause a "null pointer exception" in AvalonMailRepository much
641:                // harder to understand.
642:                if (oldName.length() > 76) {
643:                    int count = 0;
644:                    int index = 0;
645:                    while ((index = oldName.indexOf('!', index + 1)) >= 0) {
646:                        count++;
647:                    }
648:                    // It looks like a configuration loop. It's better to stop.
649:                    if (count > 7) {
650:                        throw new MessagingException(
651:                                "Unable to create a new message name: too long."
652:                                        + " Possible loop in config.xml.");
653:                    } else {
654:                        oldName = oldName.substring(0, 76);
655:                    }
656:                }
657:
658:                StringBuffer nameBuffer = new StringBuffer(64).append(oldName)
659:                        .append("-!").append(random.nextInt(1048576));
660:                return nameBuffer.toString();
661:            }
662:
663:            public String getMailetInfo() {
664:                return "DSNBounce Mailet";
665:            }
666:
667:            /* ******************************************************************** */
668:            /* ****************** Begin of getX and setX methods ****************** */
669:            /* ******************************************************************** */
670:
671:            /** Gets the expected init parameters.  */
672:            protected String[] getAllowedInitParameters() {
673:                String[] allowedArray = { "debug", "passThrough",
674:                        "messageString", "attachment", "sender", "prefix" };
675:                return allowedArray;
676:            }
677:
678:            /**
679:             * @return the <CODE>attachment</CODE> init parameter, or <CODE>MESSAGE</CODE> if missing
680:             */
681:            protected int getAttachmentType() throws MessagingException {
682:                return getTypeCode(getInitParameter("attachment", "message"));
683:            }
684:
685:            /**
686:             * @return <CODE>SpecialAddress.REVERSE_PATH</CODE>
687:             */
688:            protected Collection getRecipients() {
689:                Collection newRecipients = new HashSet();
690:                newRecipients.add(SpecialAddress.REVERSE_PATH);
691:                return newRecipients;
692:            }
693:
694:            /**
695:             * @return <CODE>SpecialAddress.REVERSE_PATH</CODE>
696:             */
697:            protected InternetAddress[] getTo() {
698:                InternetAddress[] apparentlyTo = new InternetAddress[1];
699:                apparentlyTo[0] = SpecialAddress.REVERSE_PATH
700:                        .toInternetAddress();
701:                return apparentlyTo;
702:            }
703:
704:            /**
705:             * @return <CODE>SpecialAddress.NULL</CODE> (the meaning of bounce)
706:             */
707:            protected MailAddress getReversePath(Mail originalMail) {
708:                return SpecialAddress.NULL;
709:            }
710:
711:            /* ******************************************************************** */
712:            /* ******************* End of getX and setX methods ******************* */
713:            /* ******************************************************************** */
714:
715:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.