Subversion Repositories SmartDukaan

Rev

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