vishal palla
vishal palla

Reputation: 41

How to send a calendar invite through java , so that we don't need to open .ics file

How to send a calendar invite through java , so that we don't need to open .ics file and add to calendar. When we send a mail to outlook, it should attach as direct meeting invite , i don't want to open the .ics file and add explicitly to calendar. Is it possible to do it in java or not. Even when we use ICal4J also these .ics file is not adding automatically to the calendar.

public void send(Appointment appointment, String host) throws Exception {

        try {

            Properties prop = new Properties();
            prop.put("mail.smtp.host", host);
            prop.put("mail.smtp.port", "25");
            prop.put("mail.smtp.auth", "false");
            prop.put("mail.smtp.starttls.enable", "false");

            Session session = Session.getDefaultInstance(prop, null);
            // Define message
            MimeMessage message = new MimeMessage(session);

            String toMa = StringUtils.getCommaDelimitedStringfromStringList(appointment.getTo());
            String ccMa = null;
            if(Objects.nonNull(appointment.getCc())) {
             ccMa = StringUtils.getCommaDelimitedStringfromStringList(appointment.getCc());
            }

            message.setFrom(new InternetAddress(appointment.getFrom()));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toMa));
            message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccMa));
            message.setSubject(appointment.getSubject());
            message.setHeader("Content-class", "urn:content-classes:calendarmessage");

            String content = getBufferString(appointment);
            // Create the message part
            BodyPart messageBodyPart = new MimeBodyPart();

            // Fill the message
            messageBodyPart.setHeader("Content-class", "urn:content-  classes:calendarmessage");
            messageBodyPart.setContent(appointment.getContent(),"mailBody");
            messageBodyPart.setDataHandler(new DataHandler(new ByteArrayDataSource(content, "text/calendar; charset=utf-8; method=REQUEST'")));// very
                                                                                                                // important
            // new
            MimeBodyPart bc = new MimeBodyPart();
            bc.setContent(appointment.getContent(),"text/html");
            BodyPart messageBody = bc;
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(messageBody);
            multipart.addBodyPart(messageBodyPart);
            message.setContent(multipart);
            // send message
            Transport.send(message);
        }
        catch (Exception ex) {
            log.error("exception", ex);
        }
        
    }


private String getBufferString(Appointment appointment) {
        
        StringBuffer sb = new StringBuffer();

        StringBuffer buffer = sb.append("BEGIN:VCALENDAR\n"+
        "PRODID:-Asset View 2.0\n"+
        "VERSION:2.0\n" +
        "METHOD:REQUEST\n" +
        "BEGIN:VEVENT\n" +
        "DTSTAMP:"+extracted(FORMATED_DATE_TIME, 0, null)+"\n" +
        "LOCATION:"+appointment.getLocation()+"\n" +
        extractDstartDend(appointment)+
        createRecurring(appointment)+"\n"+
        "UID:"+UUID.randomUUID().toString()+"\n" +
        "DESCRIPTION:"+appointment.getContent().substring(3, appointment.getContent().length() - 4)+"\n" +
        "SUMMARY:"+appointment.getSubject()+"\n" +
        "ORGANIZER:MAILTO:"+appointment.getFrom()+"\n" +
        "X-MS-OLK-FORCEINSPECTOROPEN:TRUE\n"+
        "X-WR-RELCALID:{0000002E-9CDF-9CE8-AD4C-66FC0A5A25F7}\n"+
        String.format("ATTENDEE;CN=%s;RSVP=TRUE:mailto:%s",
                appointment.getTo().stream().findFirst().orElse(null),
                appointment.getTo().stream().findFirst().orElse(null))+"\n"+        
        "X-MICROSOFT-CDO-BUSYSTATUS:FREE"+"\n"+
        "BEGIN:VALARM\n" +
        "ACTION:DISPLAY\n" +
        "DESCRIPTION:Reminder\n" +
        "TRIGGER:-P1D\n" +
        "END:VALARM\n" +
        "END:VEVENT\n" +
        "END:VCALENDAR");
        
        return buffer.toString();
    }

Upvotes: 1

Views: 1962

Answers (1)

vishal palla
vishal palla

Reputation: 41

I found the missing piece in my code and removed unneccesary code, which is most important. "method=REQUEST"

    public void send(Appointment appointment, String host) throws Exception {

        try {

            Properties prop = new Properties();
            prop.put("mail.smtp.host", host);

            Session session = Session.getDefaultInstance(prop, null);
            // Define message
            MimeMessage message = new MimeMessage(session);
            message.addHeaderLine("method=REQUEST");
            message.addHeaderLine("charset=UTF-8");
            message.addHeaderLine("component=VEVENT");

            String toMa = StringUtils.getCommaDelimitedStringfromStringList(appointment.getTo());
            String ccMa = null;
            if (Objects.nonNull(appointment.getCc())) {
                ccMa = StringUtils.getCommaDelimitedStringfromStringList(appointment.getCc());
                message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccMa));
            }

            message.setFrom(new InternetAddress(appointment.getFrom()));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toMa));
            
            message.setSubject(appointment.getSubject());
            message.setHeader("Content-class", "urn:content-classes:calendarmessage");

            String content = getBufferString(appointment);
            // Create the message part
            BodyPart messageBodyPart = new MimeBodyPart();

            // Fill the message
            messageBodyPart.setHeader("Content-Class", "urn:content-  classes:calendarmessage");
            messageBodyPart.setHeader("Content-ID", "calendar_message");
            messageBodyPart.setDataHandler(new DataHandler(new ByteArrayDataSource(content, "text/calendar;method=REQUEST")));// very
                                                                                                                // important
            // new
            MimeBodyPart bc = new MimeBodyPart();
            bc.setContent(appointment.getContent(), "text/html");
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(bc);
            multipart.addBodyPart(messageBodyPart);
            message.setContent(multipart);
            // send message
            Transport.send(message);
        }
        catch (Exception ex) {
            log.error("exception", ex);
        }

    }

    private String getBufferString(Appointment appointment) {

        StringBuilder sb = new StringBuilder();

        StringBuilder buffer = sb.append(
                "BEGIN:VCALENDAR\n" 
                + "PRODID: Asset View 2.0\n" 
                + "VERSION:2.0\n"
                + "METHOD:REQUEST\n" 
                + "BEGIN:VEVENT\n" 
                + "DTSTAMP:" + extracted(FORMATED_DATE_TIME, 0, null) + "\n"
                + "LOCATION:" + appointment.getLocation() + "\n" 
                + extractDstartDend(appointment)
                + createRecurring(appointment) 
                + "UID:" + UUID.randomUUID().toString() + "\n" 
                + "DESCRIPTION:"+ appointment.getContent() +"\n"
                + "X-ALT-DESC;FMTTYPE=text/html:"+ appointment.getContent() + "\n" 
                + "SUMMARY:"+ appointment.getSubject() + "\n"
                + "ORGANIZER:MAILTO:" + appointment.getFrom() + "\n"
                + String.format("ATTENDEE;CN=%s;RSVP=TRUE:mailto:%s",
                        appointment.getTo().stream().findFirst().orElse(null),
                        appointment.getTo().stream().findFirst().orElse(null))+ "\n" 
                + "X-MICROSOFT-CDO-BUSYSTATUS:FREE" + "\n"
                + "BEGIN:VALARM\n"
                + "ACTION:DISPLAY\n"
                + "DESCRIPTION:Reminder\n"
                + "TRIGGER:-P1D\n"
                + "END:VALARM\n" 
                + "END:VEVENT\n" 
                +"END:VCALENDAR");

        return buffer.toString();
    }

    private String createRecurring(Appointment appointment) {

        String res = "";
        if (appointment.getRecurringFrequency() != null && appointment.getRecurringFrequency().intValue() != 0) {

            String frequency = getFrequencyString(appointment.getRecurringFrequency().intValue());

            if (appointment.getRecurringEndDate() == null) {
                res = "RRULE:FREQ=" + frequency + "\n";
            }

            else {
                String date = extracted(FORMATED_DATE_TIME, 0, appointment.getRecurringEndDate());
                res = "RRULE:FREQ=" + frequency + ";UNTIL=" + date + "\n";
            }
        }

        return res;
    }

    private String extractDstartDend(Appointment appointment) {
        StringBuilder res = new StringBuilder();
        if (appointment.isIsAllDayEvent()) {

            res.append("DTSTART:" + extracted(FORMATED_DATE, 0, appointment.getStartDate()) + "\n");
            res.append("DTEND:" + extracted(FORMATED_DATE, 1, appointment.getStartDate()) + "\n");

        }
        else {
            res.append("DTSTART:" + extracted(FORMATED_DATE_TIME, 0, appointment.getStartDate()) + "\n");
            res.append("DTEND:" + extracted(FORMATED_DATE_TIME, 0, appointment.getEndDate()) + "\n");
        }
        return res.toString();
    }

Upvotes: 2

Related Questions