fr.xebia.cloud.amazon.aws.tools.AmazonAwsToolsSender.java Source code

Java tutorial

Introduction

Here is the source code for fr.xebia.cloud.amazon.aws.tools.AmazonAwsToolsSender.java

Source

/*
 * Copyright 2008-2010 Xebia and the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package fr.xebia.cloud.amazon.aws.tools;

import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Nonnull;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import com.amazonaws.services.identitymanagement.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.identitymanagement.AmazonIdentityManagement;
import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient;
import com.amazonaws.services.identitymanagement.model.StatusType;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Resources;

import fr.xebia.cloud.cloudinit.FreemarkerUtils;

/**
 * Send Amazon AWS tools / command lines links and install instructions by email
 * 
 * @author <a href="mailto:ebriand@xebia.fr">Eric Briand</a>
 */
public class AmazonAwsToolsSender {

    public static void main(String[] args) throws Exception {
        try {
            AmazonAwsToolsSender amazonAwsToolsSender = new AmazonAwsToolsSender();
            amazonAwsToolsSender.sendEmails();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected AmazonEC2 ec2;

    protected AmazonIdentityManagement iam;

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    protected Session mailSession;

    protected Transport mailTransport;
    protected InternetAddress mailFrom;

    protected AmazonSimpleEmailService ses;

    public AmazonAwsToolsSender() {
        try {

            InputStream credentialsAsStream = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("AwsCredentials.properties");
            Preconditions.checkNotNull(credentialsAsStream,
                    "File '/AwsCredentials.properties' NOT found in the classpath");
            AWSCredentials awsCredentials = new PropertiesCredentials(credentialsAsStream);
            iam = new AmazonIdentityManagementClient(awsCredentials);

            ses = new AmazonSimpleEmailServiceClient(awsCredentials);

            ec2 = new AmazonEC2Client(awsCredentials);
            ec2.setEndpoint("ec2.eu-west-1.amazonaws.com");

            InputStream smtpPropertiesAsStream = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("smtp.properties");
            Preconditions.checkNotNull(smtpPropertiesAsStream,
                    "File '/smtp.properties' NOT found in the classpath");

            final Properties smtpProperties = new Properties();
            smtpProperties.load(smtpPropertiesAsStream);

            mailSession = Session.getInstance(smtpProperties, null);
            mailTransport = mailSession.getTransport();
            if (smtpProperties.containsKey("mail.username")) {
                mailTransport.connect(smtpProperties.getProperty("mail.username"),
                        smtpProperties.getProperty("mail.password"));
            } else {
                mailTransport.connect();
            }
            try {
                mailFrom = new InternetAddress(smtpProperties.getProperty("mail.from"));
            } catch (Exception e) {
                throw new MessagingException("Exception parsing 'mail.from' from 'smtp.properties'", e);
            }

        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
    }

    /**
     * <p>
     * Send the tools info by email.
     * </p>
     * 
     * @param userName
     *            valid email used as userName.
     */
    public void sendEmail(@Nonnull final String userName) throws Exception {
        Preconditions.checkNotNull(userName, "Given userName can NOT be null");
        logger.debug("Process user {}", userName);

        Map<String, String> templatesParams = Maps.newHashMap();
        templatesParams.put("awsCredentialsHome", "~/.aws");
        templatesParams.put("awsCommandLinesHome", "~/aws-tools");
        templatesParams.put("awsCredentialsWindowsHome", "c:\\aws");
        templatesParams.put("awsCommandLinesWindowsHome", "c:\\aws-tools");
        templatesParams.put("userName", userName);

        User user;

        try {
            user = iam.getUser(new GetUserRequest().withUserName(userName)).getUser();
        } catch (NoSuchEntityException e) {
            logger.debug("User {} does not exist,", userName, e);
            throw e;
        }

        List<BodyPart> attachments = Lists.newArrayList();

        templatesParams.put("credentialsFileName", "aws-credentials.txt");

        // X509 SELF SIGNED CERTIFICATE
        Collection<SigningCertificate> certificates = iam
                .listSigningCertificates(new ListSigningCertificatesRequest().withUserName(user.getUserName()))
                .getCertificates();
        // filter active certificates
        certificates = Collections2.filter(certificates, new Predicate<SigningCertificate>() {
            @Override
            public boolean apply(SigningCertificate signingCertificate) {
                return StatusType.Active.equals(StatusType.fromValue(signingCertificate.getStatus()));
            }
        });

        SigningCertificate signingCertificate = Iterables.getFirst(certificates, null);
        templatesParams.put("X509CertificateFileName", "cert-" + signingCertificate.getCertificateId() + ".pem");
        templatesParams.put("X509PrivateKeyFileName", "pk-" + signingCertificate.getCertificateId() + ".pem");

        sendEmail(templatesParams, attachments, userName);
    }

    public void sendEmails() {
        URL emailsToVerifyURL = Thread.currentThread().getContextClassLoader().getResource("users-to-notify.txt");
        Preconditions.checkNotNull(emailsToVerifyURL, "File 'users-to-notify.txt' NOT found in the classpath");
        Collection<String> userNames;
        try {
            userNames = Resources.readLines(emailsToVerifyURL, Charsets.ISO_8859_1);
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
        for (String userName : userNames) {
            try {
                sendEmail(userName);
            } catch (Exception e) {
                logger.error("Failure to send email to user '{}'", userName, e);
            }

            // sleep 10 seconds to prevent "Throttling exception"
            try {
                Thread.sleep(10 * 1000);
            } catch (InterruptedException e) {
                throw Throwables.propagate(e);
            }
        }
    }

    /**
     *
     * @param toAddress
     * @throws MessagingException
     */
    public void sendEmail(Map<String, String> templatesParams, List<BodyPart> attachments, String toAddress)
            throws MessagingException {

        MimeBodyPart htmlAndPlainTextAlternativeBody = new MimeBodyPart();

        // TEXT AND HTML MESSAGE (gmail requires plain text alternative,
        // otherwise, it displays the 1st plain text attachment in the preview)
        MimeMultipart cover = new MimeMultipart("alternative");
        htmlAndPlainTextAlternativeBody.setContent(cover);
        BodyPart textHtmlBodyPart = new MimeBodyPart();
        String textHtmlBody = FreemarkerUtils.generate(templatesParams,
                "/fr/xebia/cloud/amazon/aws/tools/amazon-aws-tools-email.html.ftl");
        textHtmlBodyPart.setContent(textHtmlBody, "text/html");
        cover.addBodyPart(textHtmlBodyPart);

        BodyPart textPlainBodyPart = new MimeBodyPart();
        cover.addBodyPart(textPlainBodyPart);
        String textPlainBody = FreemarkerUtils.generate(templatesParams,
                "/fr/xebia/cloud/amazon/aws/tools/amazon-aws-tools-email.txt.ftl");
        textPlainBodyPart.setContent(textPlainBody, "text/plain");

        MimeMultipart content = new MimeMultipart("related");
        content.addBodyPart(htmlAndPlainTextAlternativeBody);

        // ATTACHMENTS
        for (BodyPart bodyPart : attachments) {
            content.addBodyPart(bodyPart);
        }

        MimeMessage msg = new MimeMessage(mailSession);

        msg.setFrom(mailFrom);
        msg.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(toAddress));
        msg.addRecipient(javax.mail.Message.RecipientType.CC, mailFrom);

        msg.setSubject("[Xebia Amazon AWS Workshop] Tools installation procedure");
        msg.setContent(content);

        mailTransport.sendMessage(msg, msg.getAllRecipients());
    }

}