Subversion Repositories SmartDukaan

Rev

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