Subversion Repositories SmartDukaan

Rev

Rev 16348 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/**
 * 
 */
package in.shop2020.util;

import in.shop2020.crm.Activity;
import in.shop2020.crm.ActivityType;
import in.shop2020.crm.CRMService.Client;
import in.shop2020.crm.SearchFilter;
import in.shop2020.crm.Ticket;
import in.shop2020.crm.TicketCategory;
import in.shop2020.crm.TicketPriority;
import in.shop2020.crm.TicketStatus;
import in.shop2020.model.v1.user.User;
import in.shop2020.model.v1.user.UserContextException;
import in.shop2020.serving.auth.CRMAuthorizingRealm;
import in.shop2020.thrift.clients.CRMClient;
import in.shop2020.thrift.clients.UserClient;
import in.shop2020.util.CRMConstants;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;

import net.htmlparser.jericho.Source;

import org.apache.commons.lang.xwork.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.thrift.TException;
import org.apache.thrift.transport.TTransportException;

/**
 * @author mandeep
 * 
 */
public class CRMEmailProcessor {
    private static final int DESCRIPTION_MAX_WIDTH = 1900;
    private static final String MAILOR_DAEMON_EMAIL_ID = "mailer-daemon@googlemail.com";
    private static final Log log                   = LogFactory
    .getLog(CRMEmailProcessor.class);
    private Client           client;
    private String emailType="";

    public void processEmail(Message message) throws Exception {
        // Ignoring mails from Mailor daemon
        if (MAILOR_DAEMON_EMAIL_ID.equals(parseEmailId(message.getFrom()[0].toString()))) {
            return;
        }

        // Try parsing the ticket Id from email with subject like Saholic#123 ...
        Long ticketId = parseTicketId(message);

        if (ticketId != null) {
            log.info("Response for Ticket: " + ticketId + ": " + message);
            updateTicket(ticketId, message);
        } else {
            log.info("Mail not recognized as CRM ticket response with subject: "
                    + message.getSubject());
            log.info("Creating ticket for the same");
            createTicket(message);
        }
    }

    // Parses regex like ^.*Saholic#(\d+).*
    private Long parseTicketId(Message message) throws MessagingException, IOException {
        String subject = message.getSubject();
        if (subject == null) {
            return null;
        }
        else if (subject.contains("Undelivered Mail")) {
            return extractTicketId(convertMessageToText(message));
        }
        else {
            return extractTicketId(subject);
        }
    }

    private Long extractTicketId (String stringToSearch){
        Pattern p = Pattern.compile("(?s).*"
                + CRMConstants.CRM_SUBJECT_PREFIX_FOR_TICKET_ID
                + "(\\d+).*$");
        Matcher m = p.matcher(stringToSearch);
        if (m.matches()) {
            return Long.parseLong(m.group(1));
        } else{
                p = Pattern.compile("(?s).*"
                    + CRMConstants.PROFIT_MANDI_SUBJECT_PREFIX_FOR_TICKET_ID
                    + "(\\d+).*$");
                m = p.matcher(stringToSearch);
                if(m.matches()) {
                        return Long.parseLong(m.group(1));
                }
        }
        return null;
    }

    public Date getLastProcessedTimestamp() throws ParseException, TException {
        client = new CRMClient().getClient();
        return new Date(client.getLastEmailProcessedTimestamp());
    }

    public void updateLastProcessedTimestamp(Date date) throws TException {
        client = new CRMClient().getClient();
        client.updateLastEmailProcessedTimestamp(date.getTime());
    }

    private void updateTicket(Long ticketId, Message message) throws Exception {
        try {
            SearchFilter searchFilter = new SearchFilter();
            searchFilter.setTicketId(ticketId);
            client = new CRMClient().getClient();
            List<Ticket> tickets = client.getTickets(searchFilter);
            if (tickets == null || tickets.isEmpty()) {
                log.error("Invalid TicketId: " + ticketId);
                log.error("Not processing message with subject: " + message.getSubject());
                return;
            }

            Ticket ticket = tickets.get(0);
            Activity activity = new Activity();
            activity.setTicketId(ticketId);
            activity.setTicketAssigneeId(ticket.getAssigneeId());
            activity.setTicketCategory(ticket.getCategory());
            activity.setTicketDescription(ticket.getDescription());
            activity.setTicketPriority(ticket.getPriority());
            activity.setType(ActivityType.RECEIVED_EMAIL_FROM_CUSTOMER);
            activity.setCreatorId(CRMConstants.ADMIN_AGENT_ID);
            activity.setIsRead(false);

            if (ticket.isSetCustomerId()) {
                activity.setCustomerId(ticket.getCustomerId());
            }

            activity.setAttachments(getAttachment(message));
            activity.setDescription(convertMessageToText(message));

            if (TicketStatus.CLOSED.equals(ticket.getStatus())) {
                ticket.setStatus(TicketStatus.REOPEN);
                if(CRMAuthorizingRealm.getAgent(ticket.getAssigneeId()) == null){
                    ticket.setAssigneeId(1);
                    activity.setTicketAssigneeId(1);
                }

            }

            activity.setTicketStatus(ticket.getStatus());

            client = new CRMClient().getClient();
            client.updateTicket(ticket, activity);
        } catch (Exception e) {
            log.error("Could not update ticket " + ticketId + " with mail "
                    + message, e);
            throw e;
        }
    }

    private void createTicket(Message message) throws MessagingException,
    IOException, TException, UserContextException {
        String description = convertMessageToText(message);
        Ticket ticket = new Ticket();
        ticket.setCreatorId(CRMConstants.ADMIN_AGENT_ID);
        
        Address[] recipients = message.getRecipients(RecipientType.TO);
        List<String> emailToIds = new ArrayList<String>();
        for(Address address: recipients){
                emailToIds.add(address.toString());
        }        
        if (getEmailType().equalsIgnoreCase("BulkEmail")){
            ticket.setCategory(TicketCategory.Bulk_Order_ENQUIRY);
        }
        else{
                if(emailToIds.contains("help@smartdukaan.com")){
                        ticket.setCategory(TicketCategory.PROFITMANDI_OTHER);
                } else {
                        ticket.setCategory(TicketCategory.OTHER);
                }
        }
        String customerEmailId = parseEmailId(message.getFrom()[0].toString());

        in.shop2020.model.v1.user.UserContextService.Client userClient = new UserClient()
        .getClient();
        User user = userClient.getUserByEmail(customerEmailId);

        if (user == null || user.getUserId() == -1) {
            ticket.setCustomerEmailId(customerEmailId);
        } else {
            ticket.setCustomerId(user.getUserId());
        }

        if(emailToIds.contains("help@smartdukaan.com")){
                ticket.setCustomerEmailId(customerEmailId);
                if(user != null && user.getUserId() != -1)
                        ticket.setCustomerId(user.getUserId());
        }
        ticket.setDescription(description);
        ticket.setPriority(TicketPriority.MEDIUM);
        ticket.setStatus(TicketStatus.OPEN);

        log.info("Creating activity!");
        Activity activity = new Activity();
        activity.setDescription(description);
        activity.setAttachments(getAttachment(message));
        activity.setTicketCategory(ticket.getCategory());
        activity.setTicketDescription(ticket.getDescription());
        activity.setTicketPriority(ticket.getPriority());
        activity.setTicketStatus(ticket.getStatus());
        activity.setType(ActivityType.RECEIVED_EMAIL_FROM_CUSTOMER);
        if(emailToIds.contains("help@smartdukaan.com")){
                activity.setTicketAssigneeId(34);
        }
        activity.setCreatorId(CRMConstants.ADMIN_AGENT_ID);
        activity.setIsRead(false);

        client = new CRMClient().getClient();
        client.insertTicket(ticket, activity);
    }

    // parsing email Id from strings like
    // "Pankaj Jain <ponkoj@hotmail.com>"
    private String parseEmailId(String address) {
        Pattern p = Pattern.compile("^.*<(.+)>.*$");
        Matcher m = p.matcher(address);
        if (m.matches()) {
            address = m.group(1);
        }

        return address;
    }

    private String convertMessageToText(Message message)
    throws MessagingException, IOException {
        String messageContent = getText(message);

        String content = "From: " + message.getFrom()[0].toString()
        + "\n\nSubject: " + message.getSubject() + "\n\nBody: "
        + messageContent;

        if (content.length() > CRMConstants.DESCRIPTION_MAX_WIDTH) {
            content = content.substring(0, CRMConstants.DESCRIPTION_MAX_WIDTH);
            content += "\n\nTHIS TEXT IS TRUNCATED. PLEASE VISIT INBOX TO SEE COMPLETE DETAILS.";
        }

        return content;
    }

    /**
     * Return the primary text content of the message.
     */
    private String getText(Part p) throws MessagingException, IOException {
        if (p.isMimeType("text/*")) {
            String s = (String) p.getContent();
            if (p.isMimeType("text/html")) {
                return new Source(s).getTextExtractor().toString();
            }
            else {
                return s;
            }
        }

        if (p.isMimeType("multipart/alternative")) {
            // prefer plain text over html text
            Multipart mp = (Multipart) p.getContent();
            String text = null;
            for (int i = 0; i < mp.getCount(); i++) {
                Part bp = mp.getBodyPart(i);
                if (bp.isMimeType("text/html")) {
                    if (text == null)
                        text = getText(bp);
                    continue;
                } else if (bp.isMimeType("text/plain")) {
                    String s = getText(bp);
                    if (s != null)
                        return s;
                } else {
                    return getText(bp);
                }
            }
            return text;
        } else if (p.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) p.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                String s = getText(mp.getBodyPart(i));
                if (s != null)
                    return s;
            }
        }

        return null;
    }

    private String getAttachment(Part p) throws MessagingException, IOException {
        String listOfFiles = "";

        if (p.isMimeType("multipart/*")) {
            Multipart multipart = (Multipart) p.getContent();
            for (int x = 0; x < multipart.getCount(); x++) {
                BodyPart bodyPart = multipart.getBodyPart(x);

                if(!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
                    continue; // we want attachments only
                }

                String fileName = bodyPart.getFileName();
                fileName = fileName+"_"+getTimeInMilliseconds();
                InputStream is = bodyPart.getInputStream();
                File f = new File(CRMConstants.ATTACHMENTS_ARCHIVE_DIR + fileName);
                FileOutputStream fos = new FileOutputStream(f);
                byte[] buf = new byte[4096];
                int bytesRead;

                while((bytesRead = is.read(buf)) != -1) {
                    fos.write(buf, 0, bytesRead);
                }

                fos.close();
                listOfFiles += fileName + ";";

                if (listOfFiles.length() > DESCRIPTION_MAX_WIDTH) {
                    listOfFiles = listOfFiles.substring(0, DESCRIPTION_MAX_WIDTH);
                    listOfFiles += "\n\nTHIS TEXT IS TRUNCATED. PLEASE VISIT INBOX TO SEE COMPLETE DETAILS.";
                }//end of if
            }//end for loop
        }//end if

        return listOfFiles.isEmpty() ? null : listOfFiles;
    }//end getAttachment
    
    public String getTimeInMilliseconds(){
        Calendar cal=GregorianCalendar.getInstance();
        return String.valueOf(cal.getTimeInMillis());
    }

    public void setEmailType(String emailType) {
        this.emailType = emailType;
    }

    public String getEmailType() {
        return emailType;
    }
}//end Class