git-svn-id: http://zxing.googlecode.com/svn/trunk@574 59b500cc-1b3d-0410-9834-0bbf25f...
[zxing.git] / zxingorg / src / com / google / zxing / web / DecodeEmailTask.java
1 /*
2  * Copyright 2008 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.web;
18
19 import com.google.zxing.MultiFormatReader;
20 import com.google.zxing.Reader;
21 import com.google.zxing.ReaderException;
22 import com.google.zxing.Result;
23 import com.google.zxing.client.j2se.BufferedImageMonochromeBitmapSource;
24
25 import javax.imageio.ImageIO;
26 import javax.mail.Address;
27 import javax.mail.Authenticator;
28 import javax.mail.Flags;
29 import javax.mail.Folder;
30 import javax.mail.Message;
31 import javax.mail.MessagingException;
32 import javax.mail.Session;
33 import javax.mail.Store;
34 import javax.mail.Transport;
35 import javax.mail.Service;
36 import javax.mail.internet.InternetAddress;
37 import javax.mail.internet.MimeBodyPart;
38 import javax.mail.internet.MimeMessage;
39 import javax.mail.internet.MimeMultipart;
40 import java.awt.image.BufferedImage;
41 import java.io.UnsupportedEncodingException;
42 import java.io.IOException;
43 import java.util.Properties;
44 import java.util.TimerTask;
45 import java.util.logging.Level;
46 import java.util.logging.Logger;
47
48 /**
49  * A {@link TimerTask} which repeatedly checks an e-mail account for messages with an attached
50  * image. When one is found it attempts to decode the image and replies with the decoded messages
51  * by e-mail.
52  *
53  * @author Sean Owen (srowen@google.com)
54  */
55 final class DecodeEmailTask extends TimerTask {
56
57   private static final Logger log = Logger.getLogger(DecodeEmailTask.class.getName());
58
59   private static final String SMTP_HOST = "smtp.gmail.com";
60   private static final String POP_HOST = "pop.gmail.com";
61   private static final String SMTP_PORT = "465";
62   private static final String POP_PORT = "995";
63   private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
64   private static final Properties sessionProperties = new Properties();
65   static {
66     sessionProperties.setProperty("mail.transport.protocol", "smtp");
67     sessionProperties.setProperty("mail.smtp.host", SMTP_HOST);
68     sessionProperties.setProperty("mail.smtp.auth", "true");
69     sessionProperties.setProperty("mail.smtp.port", SMTP_PORT);
70     sessionProperties.setProperty("mail.smtp.socketFactory.port", SMTP_PORT);
71     sessionProperties.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
72     sessionProperties.setProperty("mail.smtp.socketFactory.fallback", "false");
73     sessionProperties.setProperty("mail.smtp.quitwait", "false");
74     sessionProperties.setProperty("mail.pop3.host", POP_HOST);
75     sessionProperties.setProperty("mail.pop3.auth", "true");
76     sessionProperties.setProperty("mail.pop3.port", POP_PORT);
77     sessionProperties.setProperty("mail.pop3.socketFactory.port", POP_PORT);
78     sessionProperties.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
79     sessionProperties.setProperty("mail.pop3.socketFactory.fallback", "false");
80   }
81
82   private final Authenticator emailAuthenticator;
83   private final Address fromAddress;
84
85   DecodeEmailTask(String emailAddress, Authenticator emailAuthenticator) {
86     this.emailAuthenticator = emailAuthenticator;
87     try {
88       fromAddress = new InternetAddress(emailAddress, "ZXing By Email");
89     } catch (UnsupportedEncodingException uee) {
90       // Can't happen?
91       throw new RuntimeException(uee);
92     }
93   }
94
95   @Override
96   public void run() {
97     log.info("Checking email...");
98     Session session = Session.getInstance(sessionProperties, emailAuthenticator);
99     Store store = null;
100     Folder inbox = null;
101     try {
102       store = session.getStore("pop3");
103       store.connect();
104       inbox = store.getFolder("INBOX");
105       inbox.open(Folder.READ_WRITE);
106       int count = inbox.getMessageCount();
107       if (count > 0) {
108         log.info("Found " + count + " messages");
109       }
110       for (int i = 1; i <= count; i++) {
111         log.info("Processing message " + i);
112         Message message = inbox.getMessage(i);
113         processMessage(session, message);
114       }
115     } catch (Throwable t) {
116       log.log(Level.WARNING, "Unexpected error", t);
117     } finally {
118       closeResources(store, inbox);
119     }
120   }
121
122   private void processMessage(Session session, Message message) throws MessagingException, IOException {
123     Object content = message.getContent();
124     if (content instanceof MimeMultipart) {
125       MimeMultipart mimeContent = (MimeMultipart) content;
126       int numParts = mimeContent.getCount();
127       for (int j = 0; j < numParts; j++) {
128         MimeBodyPart part = (MimeBodyPart) mimeContent.getBodyPart(j);
129         processMessagePart(session, message, part);
130       }
131     }
132     message.setFlag(Flags.Flag.DELETED, true);
133   }
134
135   private void processMessagePart(Session session, Message message, MimeBodyPart part)
136       throws MessagingException, IOException {
137     String contentType = part.getContentType();
138     if (contentType.startsWith("image/")) {
139       BufferedImage image = ImageIO.read(part.getInputStream());
140       if (image != null) {
141         Reader reader = new MultiFormatReader();
142         Result result = null;
143         try {
144           result = reader.decode(new BufferedImageMonochromeBitmapSource(image), DecodeServlet.HINTS);
145         } catch (ReaderException re) {
146           log.info("Decoding FAILED");
147         }
148
149         Message reply = new MimeMessage(session);
150         Address sender = message.getFrom()[0];
151         reply.setRecipient(Message.RecipientType.TO, sender);
152         reply.setFrom(fromAddress);
153         if (result == null) {
154           reply.setSubject("Decode failed");
155           reply.setContent("Sorry, we could not decode that image.", "text/plain");
156         } else {
157           String text = result.getText();
158           reply.setSubject("Decode succeeded");
159           reply.setContent(text, "text/plain");
160         }
161         log.info("Sending reply");
162         Transport.send(reply);
163       }
164     }
165   }
166
167   private static void closeResources(Service service, Folder inbox) {
168     try {
169       if (inbox != null) {
170         inbox.close(true);
171       }
172       if (service != null) {
173         service.close();
174       }
175     } catch (MessagingException me) {
176       // continue
177     }
178   }
179
180   public static void main(String[] args) {
181     String emailAddress = args[0];
182     String emailPassword = args[1];
183     Authenticator emailAuthenticator = new EmailAuthenticator(emailAddress, emailPassword);
184     new DecodeEmailTask(emailAddress, emailAuthenticator).run();
185   }
186
187 }