Java tutorial
/** * Copyright 2014 Google Inc. All rights reserved. * * 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 foo.domaintest.email; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableSet; import com.google.common.io.CharStreams; import foo.domaintest.action.Action; import foo.domaintest.action.RequestModule; import foo.domaintest.metrics.impl.MetricsModule; import dagger.Module; import dagger.Provides; import org.apache.commons.fileupload.FileItemIterator; import org.apache.commons.fileupload.FileItemStream; import org.apache.commons.fileupload.FileUploadException; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.annotation.Documented; import java.util.Collections; import java.util.Set; import javax.inject.Qualifier; import javax.inject.Singleton; import javax.mail.MessagingException; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.InternetHeaders; /** Dagger module for creating the email api actions. */ @Module(addsTo = RequestModule.class, includes = MetricsModule.class, injects = { AutoreplyAction.class }) public class EmailApiModule { public static final Set<Class<? extends Action>> ACTIONS = ImmutableSet .<Class<? extends Action>>of(AutoreplyAction.class); /** Binding annotation for all unparsed email headers. */ @Qualifier @Documented public @interface RawEmailHeaders { } /** Binding annotation for parsed email headers. */ @Qualifier @Documented public @interface EmailHeader { String value(); } /** * Provides parsed email headers from the "headers" param in a multipart/form-data request. * <p> * Although SendGrid parses some headers for us, it doesn't parse "reply-to", so we need to do * this. Once we are doing it, it's easier to be consistent and use this as the sole source of * truth for information that originates in the headers. */ @Provides @Singleton InternetHeaders provideHeaders(FileItemIterator iterator) { try { while (iterator != null && iterator.hasNext()) { FileItemStream item = iterator.next(); // SendGrid sends us the headers in the "headers" param. if (item.getFieldName().equals("headers")) { try (InputStream stream = item.openStream()) { // SendGrid always sends headers in UTF-8 encoding. return new InternetHeaders(new ByteArrayInputStream( CharStreams.toString(new InputStreamReader(stream, UTF_8.name())).getBytes(UTF_8))); } } } } catch (MessagingException | FileUploadException | IOException e) { // If we fail parsing the headers fall through returning the empty header object below. } return new InternetHeaders(); // Parsing failed or there was no "headers" param. } @Provides @RawEmailHeaders @SuppressWarnings("unchecked") String provideRawEmailHeaders(InternetHeaders headers) { return Joiner.on("\r\n").join(Collections.list(headers.getAllHeaderLines())); } @Provides @EmailHeader("from") String provideFrom(InternetHeaders headers) { return getAddressHeader(headers, "from"); } @Provides @EmailHeader("reply-to") String provideReplyTo(InternetHeaders headers) { return getAddressHeader(headers, "reply-to"); } @Provides @EmailHeader("to") String provideTo(InternetHeaders headers) { return getAddressHeader(headers, "to"); } @Provides @EmailHeader("subject") String provideSubject(InternetHeaders headers) { return getHeader(headers, "subject"); } @Provides @EmailHeader("message-id") String provideMessageId(InternetHeaders headers) { return getHeader(headers, "message-id"); } @Provides @EmailHeader("references") String provideReferences(InternetHeaders headers) { return getHeader(headers, "references"); } @Provides @EmailHeader("in-reply-to") String provideInReplyTo(InternetHeaders headers) { return getHeader(headers, "in-reply-to"); } /** Parse an email from a header that may be of the form {@code First Last <name@example.tld>}. */ public String getAddressHeader(InternetHeaders headers, String headerName) { try { String header = getHeader(headers, headerName); if (header == null) { return null; } // The "false" argument means use loose validation when parsing addresses out of the header. InternetAddress[] addresses = InternetAddress.parseHeader(header, false); return addresses == null || addresses.length == 0 ? null : addresses[0].getAddress(); } catch (AddressException e) { return null; } } private String getHeader(InternetHeaders headers, String headerName) { // The "null" argument means ignore all but the first instance of the header. return headers.getHeader(headerName, null); } }