Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
ChrisPaine
Active Contributor

Hello again, just a short post this time. I picked up on some of the feedback from my first post about sending emails from NetWeaver Cloud, and have made a couple of enhancements to the solution that I thought I'd share.

Users will be users, and networks will be networks.

One of the fun things about using a RESTful design is there is no guarantee of the order in which entries will be processed. A user might submit a time sheet entry for 5 Feb 2013 and then 1 Feb 2013 and then 3 Feb 2013, or they might submit them in order but a network routing bug means the second gets processed before the first - yet they get confused if you present them the entries in that muddled order in the email that they get back.

So I implemented a very simple sorting routine to allow the entries to always be sorted in date order in the output:

public void sendMail() {
                           MailEventSender mailer = new MailEventSender();
                                // sort the entries by date first!
                                Comparator<TimeSheetEntry> comparator = new Comparator<TimeSheetEntry>() {
                                                public int compare(TimeSheetEntry c1, TimeSheetEntry c2) {
                                                                SimpleDateFormat formatter = new SimpleDateFormat("yyyymmdd");
                                                                try {
                                                                                Date d1 = formatter.parse(c1.getAssociatedDay().getDay());
                                                                                Date d2 = formatter.parse(c2.getAssociatedDay().getDay());
                                                                                return d1.compareTo(d2);
                                                                } catch (ParseException e) {
                                                                                return 0;
                                                                }
                                                }
                                };
                                Collections.sort(entries, comparator);
                                mailer.sendEmail(userId, entries, context, rootURL);
                }

Pretty simple, but a huge impact on user satisfaction :smile: .

It's probably worth avoiding legal complications

I found out that in Australia it's kinda illegal to email out in an automated message (especially one with a "please contact us further about this ..." text) unless you have a working unsubscribe function. (I'm no lawyer, but I think an email where we throw in our URL and telephone number, probably counts as "commercial").

Part 2Rules about sending commercial electronic messages

15  Simplified outline

                   The following is a simplified outline of this Part:

•      Unsolicited commercial electronic messages must not be sent.

•      Commercial electronic messages must include information about the individual or organisation who authorised the sending of the message.

•      Commercial electronic messages must contain a functional unsubscribe facility.

(source Spam Act 2003 - Part 2, section 15 - http://www.comlaw.gov.au/Details/C2013C00021/Html/Text#_Toc345409547 )

So given my emails kinda fall under that legislation (I think), we thought be better do something.

I added a new database field (and had to drop the db again :twisted: - which made my testers really happy - NOT!) to store a unsubscribe key.

When sending out an email I now add this key as part of a web link:

    if (user.getUnsubscribeKey() == null || user.getUnsubscribeKey().equals(""))
                              {
                                           // if a user has not had an email sent yet, they cannot be unsubscribed
                                           user.setUnsubscribeKey( UUID.randomUUID().toString());
                                           userData.store(user);
                              }
          String unsubscribeURL = rootURL + "Unsubscribe.html";

and a new method to get the link

public String getUnsubscribeHtml(String rootUrl) {
        return String
            .format("<p style=\"font-size:xx-small;\"><i>"
                           + "You have been sent this email because your email address was "
                           + "entered in the Discovery Consulting demonstration mobile application. If "
                           + "you no longer wish to receive emails from this application, please click "
                           + "<a href =\""
                           + rootUrl + "?unsubscribeKey=" + id + "-" + unsubscribeKey
                           + "\">unsubscribe from time sheet emails</a></i></p>");
}

As you can see the link contains both the user id that is being unsubscribed plus a key that is generated just for that user (this is to stop you from unsubscribing someone else by fiddling with the link address.)

The email now looks like:

with teeny tiny small print making me legally compliant.(I hope!)  :smile:

Having a nicely formatted response

By redirecting to a web page and using AJAX calls to actually de-register the user, I could manage to make my resulting unsubscribe page as nice looking as the others in my application.

I'm sure my testing team will have me re-writing the text here, but I thought it was nice of me not to put in big letters "YOU'VE ALREADY DE-REGISTERED! FOOL" :wink:

A little JavaScript helped:

$(document).ready(function() {
          var key = getURLParameter("unsubscribeKey");
          var unsubscribeURI = "unsubscribe" + "/" + key;
          var jsonData = $.parseJSON($.ajax({
                    url : unsubscribeURI,
                    dataType : "json",
                    async : false
          }).responseText);
          if (jsonData.unsubscribed == true) {
                    $("#unsubscribe_init").hide();
                    $("#unsubscribe_success").css('visibility', 'visible');
                    if (jsonData.alreadyUnsubscribed == true) {
                              $("#unsubscribe_success_again").css('visibility', 'visible');
                    }
          } else {
                    $("#unsubscribe_init").hide();
                    $("#unsubscribe_fail").css('visibility', 'visible');
          }
});
function getURLParameter(name) {
          return decodeURIComponent((new RegExp('[?|&]' + name + '='
                              + '([^&;]+?)(&|#|;|$)').exec(location.search) || [ , "" ])[1]
                              .replace(/\+/g, '%20'))
                              || null;
}

I found the get parameter code from stackoverflow - amazing how useful that site is!

and a little css hides the various messages in the page on load:

#unsubscribe_success{
                    visibility: hidden;
}
#unsubscribe_fail{
          visibility: hidden;
}
#unsubscribe_success_again{
          visibility: hidden;
}

I know it's not as RESTful as the other bits of my build. I suppose I could have built a servlet that accepted a DELETE and used the key as part of the resource URL. But it was at this point, more important to get it working.

Anyway...

As usual, there is the disclaimer, you're free to try to reuse any of this code, but don't expect it to work, that's up to you to get it working! If you do reuse, some kind of acknowledgement is always appreciated. Hope you found this post useful, it's not really a full blog, but I thought it was just a little too much to add into the comments of the previous blog (which was already stupidly long.) :smile: Thanks for reading!

2 Comments
Labels in this area