Subversion Repositories SmartDukaan

Rev

Rev 4241 | Rev 4854 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3339 mandeep.dh 1
/**
2
 * 
3
 */
4
package in.shop2020.util;
5
 
6
import in.shop2020.crm.Activity;
7
import in.shop2020.crm.ActivityType;
8
import in.shop2020.crm.CRMService.Client;
3390 mandeep.dh 9
import in.shop2020.crm.SearchFilter;
3339 mandeep.dh 10
import in.shop2020.crm.Ticket;
11
import in.shop2020.crm.TicketCategory;
12
import in.shop2020.crm.TicketPriority;
13
import in.shop2020.crm.TicketStatus;
14
import in.shop2020.model.v1.user.User;
15
import in.shop2020.model.v1.user.UserContextException;
4793 amar.kumar 16
import in.shop2020.serving.auth.CRMAuthorizingRealm;
3339 mandeep.dh 17
import in.shop2020.thrift.clients.CRMClient;
18
import in.shop2020.thrift.clients.UserClient;
4241 anupam.sin 19
import in.shop2020.util.CRMConstants;
20
import java.io.File;
21
import java.io.FileOutputStream;
3339 mandeep.dh 22
import java.io.IOException;
4241 anupam.sin 23
import java.io.InputStream;
3339 mandeep.dh 24
import java.text.ParseException;
25
import java.util.Date;
3408 mandeep.dh 26
import java.util.List;
3339 mandeep.dh 27
import java.util.regex.Matcher;
28
import java.util.regex.Pattern;
29
 
4241 anupam.sin 30
import javax.mail.BodyPart;
3339 mandeep.dh 31
import javax.mail.Message;
32
import javax.mail.MessagingException;
3368 mandeep.dh 33
import javax.mail.Multipart;
34
import javax.mail.Part;
3339 mandeep.dh 35
 
3546 mandeep.dh 36
import net.htmlparser.jericho.Source;
37
 
3339 mandeep.dh 38
import org.apache.commons.logging.Log;
39
import org.apache.commons.logging.LogFactory;
40
import org.apache.thrift.TException;
41
import org.apache.thrift.transport.TTransportException;
42
 
43
/**
44
 * @author mandeep
45
 * 
46
 */
47
public class CRMEmailProcessor {
4241 anupam.sin 48
    private static final int DESCRIPTION_MAX_WIDTH = 1900;
3369 mandeep.dh 49
    private static final String MAILOR_DAEMON_EMAIL_ID = "mailer-daemon@googlemail.com";
3339 mandeep.dh 50
    private static final Log log                   = LogFactory
51
                                                           .getLog(CRMEmailProcessor.class);
52
    private Client           client;
53
 
54
    public void processEmail(Message message) throws MessagingException,
55
            IOException, TException, UserContextException {
3369 mandeep.dh 56
        // Ignoring mails from Mailor daemon
57
        if (MAILOR_DAEMON_EMAIL_ID.equals(parseEmailId(message.getFrom()[0].toString()))) {
58
            return;
59
        }
60
 
4142 mandeep.dh 61
        // Try parsing the ticket Id from email with subject like Saholic#123 ...
3339 mandeep.dh 62
        Long ticketId = parseTicketId(message);
63
 
64
        if (ticketId != null) {
65
            log.info("Response for Ticket: " + ticketId + ": " + message);
66
            updateTicket(ticketId, message);
67
        } else {
68
            log.info("Mail not recognized as CRM ticket response with subject: "
69
                    + message.getSubject());
70
            log.info("Creating ticket for the same");
71
            createTicket(message);
72
        }
73
    }
74
 
4142 mandeep.dh 75
    // Parses regex like ^.*Saholic#(\d+).*
4241 anupam.sin 76
    private Long parseTicketId(Message message) throws MessagingException, IOException {
3339 mandeep.dh 77
        String subject = message.getSubject();
4241 anupam.sin 78
        if (subject == null) {
79
            return null;
3339 mandeep.dh 80
        }
4241 anupam.sin 81
        else if (subject.contains("Undelivered Mail")) {
82
            return extractTicketId(convertMessageToText(message));
83
        }
84
        else {
85
            return extractTicketId(subject);
86
        }
3339 mandeep.dh 87
    }
4241 anupam.sin 88
 
89
    private Long extractTicketId (String stringToSearch){
90
        Pattern p = Pattern.compile("(?s).*"
91
                + CRMConstants.CRM_SUBJECT_PREFIX_FOR_TICKET_ID
92
                + "(\\d+).*$");
93
        Matcher m = p.matcher(stringToSearch);
94
        if (m.matches()) {
95
            return Long.parseLong(m.group(1));
96
        }
97
        return null;
98
    }
3339 mandeep.dh 99
 
100
    public Date getLastProcessedTimestamp() throws ParseException, TException {
3373 mandeep.dh 101
        client = new CRMClient().getClient();
3339 mandeep.dh 102
        return new Date(client.getLastEmailProcessedTimestamp());
103
    }
104
 
105
    public void updateLastProcessedTimestamp(Date date) throws TException {
3340 mandeep.dh 106
        client = new CRMClient().getClient();
3339 mandeep.dh 107
        client.updateLastEmailProcessedTimestamp(date.getTime());
108
    }
109
 
110
    private void updateTicket(Long ticketId, Message message) {
111
        try {
3390 mandeep.dh 112
            SearchFilter searchFilter = new SearchFilter();
113
            searchFilter.setTicketId(ticketId);
3373 mandeep.dh 114
            client = new CRMClient().getClient();
3408 mandeep.dh 115
            List<Ticket> tickets = client.getTickets(searchFilter);
116
            if (tickets == null || tickets.isEmpty()) {
117
                log.error("Invalid TicketId: " + ticketId);
118
                log.error("Not processing message with subject: " + message.getSubject());
119
                return;
120
            }
121
 
122
            Ticket ticket = tickets.get(0);
3339 mandeep.dh 123
            Activity activity = new Activity();
124
            activity.setTicketId(ticketId);
125
            activity.setTicketAssigneeId(ticket.getAssigneeId());
126
            activity.setTicketCategory(ticket.getCategory());
127
            activity.setTicketDescription(ticket.getDescription());
128
            activity.setTicketPriority(ticket.getPriority());
129
            activity.setType(ActivityType.RECEIVED_EMAIL_FROM_CUSTOMER);
130
            activity.setCreatorId(CRMConstants.ADMIN_AGENT_ID);
3398 mandeep.dh 131
            activity.setIsRead(false);
3339 mandeep.dh 132
 
133
            if (ticket.isSetCustomerId()) {
134
                activity.setCustomerId(ticket.getCustomerId());
135
            }
136
 
4241 anupam.sin 137
            activity.setAttachments(getAttachment(message));
3339 mandeep.dh 138
            activity.setDescription(convertMessageToText(message));
3368 mandeep.dh 139
 
140
            if (TicketStatus.CLOSED.equals(ticket.getStatus())) {
141
                ticket.setStatus(TicketStatus.REOPEN);
4793 amar.kumar 142
                if(CRMAuthorizingRealm.getAgent(ticket.getAssigneeId()) == null){
143
                	ticket.setAssigneeId(1);
144
                	activity.setTicketAssigneeId(1);
145
                }
146
 
3368 mandeep.dh 147
            }
148
 
4196 mandeep.dh 149
            activity.setTicketStatus(ticket.getStatus());
150
 
3373 mandeep.dh 151
            client = new CRMClient().getClient();
3339 mandeep.dh 152
            client.updateTicket(ticket, activity);
153
        } catch (TTransportException e) {
154
            log.error("Could not update ticket " + ticketId + " with mail "
155
                    + message, e);
156
        } catch (TException e) {
157
            log.error("Could not update ticket " + ticketId + " with mail "
158
                    + message, e);
159
        } catch (MessagingException e) {
160
            log.error("Could not update ticket " + ticketId + " with mail "
161
                    + message, e);
162
        } catch (IOException e) {
163
            log.error("Could not update ticket " + ticketId + " with mail "
164
                    + message, e);
165
        }
166
    }
167
 
168
    private void createTicket(Message message) throws MessagingException,
169
            IOException, TException, UserContextException {
170
        String description = convertMessageToText(message);
171
        Ticket ticket = new Ticket();
172
        ticket.setCreatorId(CRMConstants.ADMIN_AGENT_ID);
173
        ticket.setCategory(TicketCategory.OTHER);
174
        String customerEmailId = parseEmailId(message.getFrom()[0].toString());
175
 
176
        in.shop2020.model.v1.user.UserContextService.Client userClient = new UserClient()
177
                .getClient();
178
        User user = userClient.getUserByEmail(customerEmailId);
179
 
180
        if (user == null || user.getUserId() == -1) {
181
            ticket.setCustomerEmailId(customerEmailId);
182
        } else {
183
            ticket.setCustomerId(user.getUserId());
184
        }
185
 
186
        ticket.setDescription(description);
187
        ticket.setPriority(TicketPriority.MEDIUM);
188
        ticket.setStatus(TicketStatus.OPEN);
189
 
190
        log.info("Creating activity!");
191
        Activity activity = new Activity();
192
        activity.setDescription(description);
4241 anupam.sin 193
        activity.setAttachments(getAttachment(message));
3339 mandeep.dh 194
        activity.setTicketCategory(ticket.getCategory());
195
        activity.setTicketDescription(ticket.getDescription());
196
        activity.setTicketPriority(ticket.getPriority());
197
        activity.setTicketStatus(ticket.getStatus());
198
        activity.setType(ActivityType.RECEIVED_EMAIL_FROM_CUSTOMER);
199
        activity.setCreatorId(CRMConstants.ADMIN_AGENT_ID);
3398 mandeep.dh 200
        activity.setIsRead(false);
3339 mandeep.dh 201
 
3373 mandeep.dh 202
        client = new CRMClient().getClient();
3339 mandeep.dh 203
        client.insertTicket(ticket, activity);
204
    }
205
 
206
    // parsing email Id from strings like
3368 mandeep.dh 207
    // "Pankaj Jain <ponkoj@hotmail.com>"
3339 mandeep.dh 208
    private String parseEmailId(String address) {
209
        Pattern p = Pattern.compile("^.*<(.+)>.*$");
210
        Matcher m = p.matcher(address);
211
        if (m.matches()) {
212
            address = m.group(1);
213
        }
214
 
215
        return address;
216
    }
217
 
218
    private String convertMessageToText(Message message)
219
            throws MessagingException, IOException {
3368 mandeep.dh 220
        String messageContent = getText(message);
3339 mandeep.dh 221
 
3368 mandeep.dh 222
        String content = "From: " + message.getFrom()[0].toString()
223
                + "\n\nSubject: " + message.getSubject() + "\n\nBody: "
224
                + messageContent;
3339 mandeep.dh 225
 
4206 mandeep.dh 226
        if (content.length() > CRMConstants.DESCRIPTION_MAX_WIDTH) {
227
            content = content.substring(0, CRMConstants.DESCRIPTION_MAX_WIDTH);
3368 mandeep.dh 228
            content += "\n\nTHIS TEXT IS TRUNCATED. PLEASE VISIT INBOX TO SEE COMPLETE DETAILS.";
3339 mandeep.dh 229
        }
230
 
231
        return content;
232
    }
3368 mandeep.dh 233
 
234
    /**
235
     * Return the primary text content of the message.
236
     */
237
    private String getText(Part p) throws MessagingException, IOException {
238
        if (p.isMimeType("text/*")) {
239
            String s = (String) p.getContent();
3546 mandeep.dh 240
            if (p.isMimeType("text/html")) {
241
                return new Source(s).getTextExtractor().toString();
242
            }
243
            else {
244
                return s;
245
            }
3368 mandeep.dh 246
        }
247
 
248
        if (p.isMimeType("multipart/alternative")) {
249
            // prefer plain text over html text
250
            Multipart mp = (Multipart) p.getContent();
251
            String text = null;
252
            for (int i = 0; i < mp.getCount(); i++) {
253
                Part bp = mp.getBodyPart(i);
254
                if (bp.isMimeType("text/html")) {
255
                    if (text == null)
256
                        text = getText(bp);
257
                    continue;
258
                } else if (bp.isMimeType("text/plain")) {
259
                    String s = getText(bp);
260
                    if (s != null)
261
                        return s;
262
                } else {
263
                    return getText(bp);
264
                }
265
            }
266
            return text;
267
        } else if (p.isMimeType("multipart/*")) {
268
            Multipart mp = (Multipart) p.getContent();
269
            for (int i = 0; i < mp.getCount(); i++) {
270
                String s = getText(mp.getBodyPart(i));
271
                if (s != null)
272
                    return s;
273
            }
274
        }
275
 
276
        return null;
277
    }
4241 anupam.sin 278
 
279
    private String getAttachment(Part p) throws MessagingException, IOException {
280
        String listOfFiles = "";
281
 
282
        if (p.isMimeType("multipart/*")) {
283
            Multipart multipart = (Multipart) p.getContent();
284
            for (int x = 0; x < multipart.getCount(); x++) {
285
                BodyPart bodyPart = multipart.getBodyPart(x);
286
 
287
                if(!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
288
                    continue; // we want attachments only
289
                }
290
 
291
                String fileName = bodyPart.getFileName();
292
                InputStream is = bodyPart.getInputStream();
293
                File f = new File(CRMConstants.ATTACHMENTS_ARCHIVE_DIR + fileName);
294
                FileOutputStream fos = new FileOutputStream(f);
295
                byte[] buf = new byte[4096];
296
                int bytesRead;
297
 
298
                while((bytesRead = is.read(buf)) != -1) {
299
                    fos.write(buf, 0, bytesRead);
300
                }
301
 
302
                fos.close();
303
                listOfFiles += fileName + ";";
304
 
305
                if (listOfFiles.length() > DESCRIPTION_MAX_WIDTH) {
306
                    listOfFiles = listOfFiles.substring(0, DESCRIPTION_MAX_WIDTH);
307
                    listOfFiles += "\n\nTHIS TEXT IS TRUNCATED. PLEASE VISIT INBOX TO SEE COMPLETE DETAILS.";
308
                }//end of if
309
            }//end for loop
310
        }//end if
311
 
312
        return listOfFiles.isEmpty() ? null : listOfFiles;
313
    }//end getAttachment
314
}//end Class