Finished work on the local binarizer and renamed it to HybridBinarizer. It uses the...
[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.BinaryBitmap;
20 import com.google.zxing.LuminanceSource;
21 import com.google.zxing.MultiFormatReader;
22 import com.google.zxing.Reader;
23 import com.google.zxing.ReaderException;
24 import com.google.zxing.Result;
25 import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
26 import com.google.zxing.common.HybridBinarizer;
27
28 import java.awt.image.BufferedImage;
29 import java.io.IOException;
30 import java.io.UnsupportedEncodingException;
31 import java.util.Properties;
32 import java.util.TimerTask;
33 import java.util.logging.Level;
34 import java.util.logging.Logger;
35
36 import javax.imageio.ImageIO;
37 import javax.mail.Address;
38 import javax.mail.Authenticator;
39 import javax.mail.Flags;
40 import javax.mail.Folder;
41 import javax.mail.Message;
42 import javax.mail.MessagingException;
43 import javax.mail.Service;
44 import javax.mail.Session;
45 import javax.mail.Store;
46 import javax.mail.Transport;
47 import javax.mail.internet.InternetAddress;
48 import javax.mail.internet.MimeBodyPart;
49 import javax.mail.internet.MimeMessage;
50 import javax.mail.internet.MimeMultipart;
51
52 /**
53  * A {@link TimerTask} which repeatedly checks an e-mail account for messages with an attached
54  * image. When one is found it attempts to decode the image and replies with the decoded messages
55  * by e-mail.
56  *
57  * @author Sean Owen
58  */
59 final class DecodeEmailTask extends TimerTask {
60
61   private static final Logger log = Logger.getLogger(DecodeEmailTask.class.getName());
62
63   private static final String SMTP_HOST = "smtp.gmail.com";
64   private static final String POP_HOST = "pop.gmail.com";
65   private static final String SMTP_PORT = "465";
66   private static final String POP_PORT = "995";
67   private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
68   private static final Properties sessionProperties = new Properties();
69   static {
70     sessionProperties.setProperty("mail.transport.protocol", "smtp");
71     sessionProperties.setProperty("mail.smtp.host", SMTP_HOST);
72     sessionProperties.setProperty("mail.smtp.auth", "true");
73     sessionProperties.setProperty("mail.smtp.port", SMTP_PORT);
74     sessionProperties.setProperty("mail.smtp.socketFactory.port", SMTP_PORT);
75     sessionProperties.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
76     sessionProperties.setProperty("mail.smtp.socketFactory.fallback", "false");
77     sessionProperties.setProperty("mail.smtp.quitwait", "false");
78     sessionProperties.setProperty("mail.pop3.host", POP_HOST);
79     sessionProperties.setProperty("mail.pop3.auth", "true");
80     sessionProperties.setProperty("mail.pop3.port", POP_PORT);
81     sessionProperties.setProperty("mail.pop3.socketFactory.port", POP_PORT);
82     sessionProperties.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
83     sessionProperties.setProperty("mail.pop3.socketFactory.fallback", "false");
84   }
85
86   private final Authenticator emailAuthenticator;
87   private final Address fromAddress;
88
89   DecodeEmailTask(String emailAddress, Authenticator emailAuthenticator) {
90     this.emailAuthenticator = emailAuthenticator;
91     try {
92       fromAddress = new InternetAddress(emailAddress, "ZXing By Email");
93     } catch (UnsupportedEncodingException uee) {
94       // Can't happen?
95       throw new RuntimeException(uee);
96     }
97   }
98
99   @Override
100   public void run() {
101     log.info("Checking email...");
102     Session session = Session.getInstance(sessionProperties, emailAuthenticator);
103     Store store = null;
104     Folder inbox = null;
105     try {
106       store = session.getStore("pop3");
107       store.connect();
108       inbox = store.getFolder("INBOX");
109       inbox.open(Folder.READ_WRITE);
110       int count = inbox.getMessageCount();
111       if (count > 0) {
112         log.info("Found " + count + " messages");
113       }
114       for (int i = 1; i <= count; i++) {
115         log.info("Processing message " + i);
116         Message message = inbox.getMessage(i);
117         processMessage(session, message);
118       }
119     } catch (Throwable t) {
120       log.log(Level.WARNING, "Unexpected error", t);
121     } finally {
122       closeResources(store, inbox);
123     }
124   }
125
126   private void processMessage(Session session, Message message) throws MessagingException,
127       IOException {
128     Object content = message.getContent();
129     if (content instanceof MimeMultipart) {
130       MimeMultipart mimeContent = (MimeMultipart) content;
131       int numParts = mimeContent.getCount();
132       for (int j = 0; j < numParts; j++) {
133         MimeBodyPart part = (MimeBodyPart) mimeContent.getBodyPart(j);
134         processMessagePart(session, message, part);
135       }
136     }
137     message.setFlag(Flags.Flag.DELETED, true);
138   }
139
140   private void processMessagePart(Session session, Message message, MimeBodyPart part)
141       throws MessagingException, IOException {
142     String contentType = part.getContentType();
143     if (contentType.startsWith("image/")) {
144       BufferedImage image = ImageIO.read(part.getInputStream());
145       if (image != null) {
146         Reader reader = new MultiFormatReader();
147         Result result = null;
148         try {
149           LuminanceSource source = new BufferedImageLuminanceSource(image);
150           BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
151           result = reader.decode(bitmap, DecodeServlet.HINTS);
152         } catch (ReaderException re) {
153           log.info("Decoding FAILED");
154         }
155
156         Message reply = new MimeMessage(session);
157         Address sender = message.getFrom()[0];
158         reply.setRecipient(Message.RecipientType.TO, sender);
159         reply.setFrom(fromAddress);
160         if (result == null) {
161           reply.setSubject("Decode failed");
162           reply.setContent("Sorry, we could not decode that image.", "text/plain");
163         } else {
164           String text = result.getText();
165           reply.setSubject("Decode succeeded");
166           reply.setContent(text, "text/plain");
167         }
168         log.info("Sending reply");
169         Transport.send(reply);
170       }
171     }
172   }
173
174   private static void closeResources(Service service, Folder inbox) {
175     try {
176       if (inbox != null) {
177         inbox.close(true);
178       }
179       if (service != null) {
180         service.close();
181       }
182     } catch (MessagingException me) {
183       // continue
184     }
185   }
186
187   public static void main(String[] args) {
188     String emailAddress = args[0];
189     String emailPassword = args[1];
190     Authenticator emailAuthenticator = new EmailAuthenticator(emailAddress, emailPassword);
191     new DecodeEmailTask(emailAddress, emailAuthenticator).run();
192   }
193
194 }