Setting up Gmail
All of the advise that most site provide is that you should allow less secure access to your Gmail account during the testing and then turn this setting off again afterwards.
Gmail 2-Step Verification
What I have found to work better is to enable 2-Step verification on your Gmail account and then to generate an App Password for the application instead of using the email account password.
App Password
Browse to the Sign-in and security section of the Gmail account and under the 2-Step Verification you’ll find the App Password section.
After confirming your password, all the App Password are displayed and a link to generate a new App Password. The App Password will be used later instead of the email account password.
Importing the Gmail certificate into the Java Keystore
I could only find two methods to retrieve the Google Gmail certificate, one being OpenSSL and the other being Python. Now my development machine is Windows and I did not want to go through the pain of setting up Cygwin only to execute one command so I instead opted for the Python approach. As a side note, I wanted to find a pure Java solution but to date have found none.
Python
import smtplib import ssl connection = smtplib.SMTP() connection.connect('smtp.gmail.com') connection.starttls() f1=open('./gmail.pem', 'w+') print >> f1, ssl.DER_cert_to_PEM_cert(connection.sock.getpeercert(binary_form=True))
The preceding code connects to smtp.gmail.com and saves the certificate in the PEM Base64 encoding.
OpenSSL
To be honest there are enough sources on the net on how to use OpenSSL to retrieve a certificate, so I will not polute the net with yet another.
Creating the certificate keystore
keytool -keystore cacerts.jks -importcert -alias gmail -file gmail.pem keytool -list -keystore cacerts.jks
I guess the commands are pretty self explanatory, since the first performs the actual creation of the cacerts.jks file with the certificate gmail.pem being aliased by the name gmail. The second command lists the certificates within the cacerts.jks file.
Providing the SSL Context Parameters
Configuration
In the application.properties define the properties for the location and the password for the keystore. A neat feature of Spring Boot is that the password can be overwritten by providing a environment variable THREESIXTY_KEYSTORE_PASSWORD which will keep the actual password away from prying eyes or opt for HashCorp Vault to keep this.
# Keystore threesixty.keystore.location=C:\\tmp\\cacerts.jks threesixty.keystore.password=password
Bean
Next provide the creation of the SSLContextParameters object from the keystore location and password for Apache Camel.
@Bean public SSLContextParameters sslContextParameters( @Value("threesixty.keystore.location") final String location, @Value("threesixty.keystore.password") final String password) { KeyStoreParameters store = new KeyStoreParameters(); store.setResource(location); store.setPassword(password); TrustManagersParameters trust = new TrustManagersParameters(); trust.setKeyStore(store); SSLContextParameters parameters = new SSLContextParameters(); parameters.setTrustManagers(trust); return parameters; }
Configuring a route to deliver a file to email
The route polls the directory for files and then enriches the exchange with a header field that will contain the attachment (i.e. the file itself) and then routes the file to the email smtps endpoint which will use the file as the body and as an attachment.
from("file:C://tmp/camel") .routeId("DELIVER001") .routeDescription("Deliver file to Gmail") .bean(new AttachmentProcessor()) .to("smtps:smtp.gmail.com:465?username=&password=&to=somebody@gmail.com&subject=Test&debugMode=true&mail.smtp.auth=true&mail.smtp.starttls.enable=true");
public class AttachmentProcessor implements Processor { @Handler public void process(Exchange exchange) { try { byte[] file = exchange.getIn().getBody(byte[].class); String fileName = exchange.getIn().getHeader("CamelFileName", String.class); String path = exchange.getIn().getHeader("CamelFileAbsolutePath", String.class); String mimeType = Files.probeContentType(Paths.get(path)); exchange.getIn().setHeader("mimeType", mimeType); exchange.getIn().addAttachment(fileName, new DataHandler(new ByteArrayDataSource(file, mimeType))); } catch (Exception e) { e.printStackTrace(); } } }
References
http://notepad2.blogspot.com/2012/04/import-gmail-certificate-into-java.html
Recent Comments