I want to send two kinds email, and some logic could shared. e.g.
try {
MimeMessage msg = javaMailService.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(msg, true, DEFAULT_ENCODING);
//custom code here ...
} catch (MessagingException e) {
logger.error("build email fail", e);
} catch (Exception e) {
logger.error("send email fail", e);
}
above is common code (e.g. sendEmail(Function customCode)), below is custom code of sending email to foo
logger.info("send count mail to {}", toFoo);
helper.setFrom(sender);
helper.setTo(toFoo);
helper.setSubject("Foo Subject");
String content = generateFooContent(foo); //use fooTemplate.ftl
helper.setText(content, true);
javaMailService.send(msg);
I want to this effect,
Function fooFunc = ()->{logger.info("send count mail to {}", toFoo);
helper.setFrom(sender);
helper.setTo(toFoo);
helper.setSubject("Foo");
String content = generateFooContent(foo);
helper.setText(content, true);
javaMailService.send(msg);}
then call sendEmail method,
sendEmail(fooFunc);
If I want to send bar message,
Function barFunc = ()->{...} //cunstom code here
sendEmail(barFunc);
In java8 could achieve this? if could how?
Your "Function" has a signature:
void doStuff(MimeMessageHelper helper)
We already have one of these - it's called a Consumer<MimeMessageHelper>.
So:
final Consumer<MimeMessageHelper> messageCreator = ...
try {
MimeMessage msg = javaMailService.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(msg, true, DEFAULT_ENCODING);
messageCreator.accept(helper);
javaMailService.send(msg);
} catch (MessagingException e) {
logger.error("build email fail", e);
} catch (Exception e) {
logger.error("send email fail", e);
}
Now, to define your sender simply use:
BiConsumer<MimeMessageHelper> fooFunc = helper -> {
logger.info("send count mail to {}", toFoo);
helper.setFrom(sender);
helper.setTo(toFoo);
helper.setSubject("Foo");
String content = generateFooContent(foo);
helper.setText(content, true);
}
P.S. please note my formatting.
Thanks #Boris the Spider, it do works, see below
private void sendFooHtmlMessage(List<Foo> body) {
BiConsumer<MimeMessage,MimeMessageHelper> fooFunc = (msg,helper) -> {
logger.info("send foo mail to {}", toFoo);
try {
helper.setTo(toFoo);
helper.setSubject("Foo Subject");
String content = generateFooContent(body);
helper.setText(content, true);
javaMailService.send(msg);
} catch (Exception e) {
}
};
sendMessage(fooFunc);
}
private void sendMessage(BiConsumer<MimeMessage,MimeMessageHelper> consumer) {
try {
final MimeMessage msg = javaMailService.createMimeMessage();
final MimeMessageHelper helper = new MimeMessageHelper(msg, true, DEFAULT_ENCODING);
helper.setFrom(sender);
consumer.accept(msg, helper);
} catch (MessagingException e) {
logger.error("build email failed", e);
} catch (Exception e) {
logger.error("send email failed", e);
}
}
but still lack something, see above code I have to catch exception in fooFunc, actually I want to throw it because in common sendMesage will catch these exception.
So I adopt another way, see below
public interface SendMessageAction {
void action(MimeMessage msg, MimeMessageHelper helper) throws MessagingException;
}
private void sendMessage(SendMessageAction action) {
//...
}
private void sendFooHtmlMessage(List<Foo> body) {
SendMessageAction fooAction = (msg, helper) -> {
logger.info("send foo mail to {}", toFoo);
//...
};
sendMessage(fooAction);
}
Related
I'm implementing a mail Sender, near 1'6000.000 mails (with images and PDF) in one day per month (closing month extract), the mails are about 12 products...
I need to fill a Message Scratch per product... in order to not read (per email) else per product.
I'm trying to implement cloning javax.mail.Message and javax.mail.Multipart in order to be faster.
AddContent to Multipart
public static void addContent(final Multipart multipart, String contenidoCorreo) throws Exception {
MimeBodyPart mimeBodyPart = new PreencodedMimeBodyPart("8bit");
mimeBodyPart.setText(contenidoCorreo, "iso-8859-1", "html");
multipart.addBodyPart(mimeBodyPart, 0);
}
Add Image per Bytes
public static void addImageToMultipart(final Multipart multipart, byte[] contenidoImagen, String nombreImagen) throws Exception {
MimeBodyPart imagenMimeBodyPart = new MimeBodyPart();
try {
ByteArrayDataSource byteArrayDataSource = new ByteArrayDataSource(contenidoImagen, "image/*");
imagenMimeBodyPart.setDataHandler(new DataHandler(byteArrayDataSource));
imagenMimeBodyPart.setFileName(nombreImagen);
imagenMimeBodyPart.setContentID("<" + nombreImagen + ">");
imagenMimeBodyPart.setDisposition(MimeBodyPart.INLINE);
multipart.addBodyPart(imagenMimeBodyPart);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
AddPDF per File
public static void addPDF(final Multipart multipart, String ruta, String nombre) throws Exception {
Path path = Paths.get(ruta, nombre);
if (path.toFile().exists()) {
MimeBodyPart preencodedMimeBodyPart = new PreencodedMimeBodyPart("base64");
preencodedMimeBodyPart.attachFile(path.toFile());
preencodedMimeBodyPart.setFileName(nombre);
preencodedMimeBodyPart.setHeader("Content-Type", "application/pdf");
preencodedMimeBodyPart.setDisposition(MimeBodyPart.ATTACHMENT);
multipart.addBodyPart(preencodedMimeBodyPart);
MimeBodyPart pdfMimeBodyPart = new MimeBodyPart();
}
My Cloning Message
public static Message cloneMessage(Message source) {
//Multiple and Separated Exceptions because maybe not all properties are defined in some time.
Message target = new MimeMessage(source.getSession());
try {
if (source.getFrom() != null && source.getFrom().length > 0) {
Address address = (source.getFrom()[0]);
target.setFrom(new InternetAddress(((InternetAddress) address).getAddress(), ((InternetAddress) address).getPersonal()));
}
} catch (Exception ex) {
//Handle Exception
}
try {
target.setSentDate((Date) (source.getSentDate().clone()));
} catch (MessagingException ex) {
//Handle Exception
}
try {
target.setRecipients(Message.RecipientType.TO, target.getRecipients(Message.RecipientType.TO).clone());
} catch (MessagingException ex) {
//Handle Exception
}
try {
Enumeration numerationHeaders = source.getAllHeaders();
while (numerationHeaders.hasMoreElements()) {
Header header = (Header) numerationHeaders.nextElement();
target.addHeader(header.getName(), header.getValue());
}
} catch (MessagingException ex) {
//Handle Exception
}
try {
target.setSubject(new String(source.getSubject()));
} catch (MessagingException ex) {
//Handle Exception
}
try {
target.setContent(cloneMultipart((Multipart)(source.getContent())));
} catch (Exception ex) {
//Handle Exception
}
return target;
}
Cloning Multipart
public static Multipart cloneMultipart(Multipart source) {
MimeMultipart target = new MimeMultipart();
try {
for (int i = 0; i < source.getCount(); i++) {
MimeBodyPart mimeBodyPart = (MimeBodyPart)source.getBodyPart(i);
mimeBodyPart //?????
}
} catch (MessagingException ex) {
//Handle Exception
}
return target;
}
How cloning Multipart?
some advice to clone Message?
How detect the Content (the used with addContent method) has been added?
I have this below code for downloading CSV as an ajax button click, But the file is not downloading. Only showing the black new tab on the browser.
#RequestMapping(value = "/batch/download", method = RequestMethod.POST, produces = "text/csv")
#ResponseBody
public void downloadNGIBatchSelected(HttpServletResponse response) throws IOException {
List<String> ids = Arrays.asList("1312321","312313");
generateNewCustomerCSV(response.getWriter(),ids);
}
private void generateNewCustomerCSV(PrintWriter writer, List<String> ids){
String NEW_LINE_SEPARATOR = "\n";
//CSV file header
Object[] FILE_HEADER = {"Token Number",
"Token Expiry Date",
};
CSVPrinter csvPrinter = null;
try {
csvPrinter = new CSVPrinter(new BufferedWriter(writer), CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR));
//Create CSV file header
csvPrinter.printRecord(FILE_HEADER);
for (PolicyMap PolicyMap : policyMaps) {
List customerCSV = new ArrayList();
customerCSV.add(PolicyMap.getInsurancePolicy().getTokenNo());
try {
csvPrinter.printRecord(customerCSV);
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
writer.flush();
writer.close();
csvPrinter.close();
} catch (IOException e) {
System.out.println("Error while flushing/closing fileWriter/csvPrinter !!!");
e.printStackTrace();
}
}
}
You have set the content type in #RequestMapping annotation. But it is not going to work in the case when response is being written using HttpServletResponse. In this case, instead of spring, HttpServletResponse is writing the response that's why you have to set the response type in the response before getting the writer.
response.setContentType ("application/csv");
response.setHeader ("Content-Disposition", "attachment; filename=\"nishith.csv\"");
I am trying to save data in authData field android, But I am getting exception: Cannot save a ParseUser that is not authenticated" after only reading the user
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.whereEqualTo("username", email);
query.findInBackground(new FindCallback<ParseUser>() {
#SuppressWarnings("deprecation")
public void done(List<ParseUser> scoreList, ParseException e) {
if (e == null) {
if(scoreList.size()>0){
facebook_user = (ParseUser) scoreList.get(0);
facebook_user.isAuthenticated()
JSONObject obj = new JSONObject();
try {
obj.put("name", "xyz");
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
facebook_user.put("authdata", obj);
facebook_user.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
// exception in this section //
//Cannot save a ParseUser that is not authenticated" after only reading the user//
});
}else{
}
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
It looks like you are attempting to modify that user with the .put() before saving:
facebook_user.put("authdata", obj);
facebook_user.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
// exception in this section //
});
If you want to change a user, you need to be logged in as the user, execute the change on Cloud Code using the masterKey, or change the user objects' ACL. Here's a SO post with a bit more info.
Let me know if you have any more questions.
I have a question regarding event listener. We have a event listener which listen to delete node event and perform some activity say "send email".
While code review i found this, although this code is working fine i am not convinced with the session being handled here :
#Activate
protected void activate(ComponentContext context) {
try{
final String path="/content/dam/";
Session session = repository.loginAdministrative(repository.getDefaultWorkspace());
observationManager = session.getWorkspace().getObservationManager();
observationManager.addEventListener(this, Event.PROPERTY_REMOVED, path, true, null, null, true);
checkOutProperty = OsgiUtil.toString(context.getProperties()
.get(ASSET_LOCK_PROPNAME_UPDATE), ASSET_LOCK_PROPNAME_DEFAULT);
if (session != null && session.isLive()) {
session.save();
}
} catch (RepositoryException e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured in activate method of Property Removed Listener class:" + e.getMessage());
}
}catch (Exception e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured in activate method of Property Removed Listener class:"+e.getMessage());
}
}
}
#Deactivate
protected void deactivate(ComponentContext componentContext) {
try {
if (observationManager != null) {
observationManager.removeEventListener(this);
}
} catch (RepositoryException e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured " + e);
}
} catch (Exception e) {
if(LOG.isErrorEnabled()){
LOG.error(e.getMessage());
}
}
}
Questions:
Best practice would be to create session object private to this class and should be logout in deactivate method?
Once an event is added in Observation Manager, do we really need session object? I was expecting if we should logout from session there.
EventListener are a bit cumbersome here. I fought many battles with JCR Sessions and Sling ResourceResolvers within them. The problem is, you need to keep the Session active as long as the Event Listener is active. So the only thing missing in your code is a logout on deactivate.
I created an AbstractEventListener which takes care of this and provides the following two methods and has two private members:
private Session session;
private ObservationManager observationManager;
protected void addEventListener(final EventListener eventListener,
final int eventTypes, final String path, final String[] nodeTypes) {
try {
session = getRepositorySession();
observationManager = session.getWorkspace().getObservationManager();
observationManager.addEventListener(eventListener, eventTypes,
path, true, null, nodeTypes, true);
} catch (RepositoryException e) {
LOGGER.error("Repository error while registering observation: ", e);
}
}
protected void removeEventListener(final EventListener eventListener) {
if (observationManager != null) {
try {
observationManager.removeEventListener(eventListener);
} catch (RepositoryException e) {
LOGGER.error(
"Repository error while unregistering observation: ", e);
} finally {
logoutSession(session);
}
}
}
And then in the actual EventListener I just call them:
protected void activate(ComponentContext context) {
addEventListener(this, Event.PROPERTY_ADDED| Event.PROPERTY_CHANGED, "/content/mysite", null);
}
}
protected void deactivate(ComponentContext componentContext) {
removeEventListener(this);
}
I keep getting a HTML 404 reply from the server when I try to login via a httppost (https). Not sure if this is a cookie problem or something else. The code should be good as I have copied it from another activity. I need some help.
This is my current code:
public int postData(String usernamne, String password) {
String url = "https://domainname.com/nclogin.submit";
HttpPost httppost = new HttpPost(url);
try {
KeyStore trusted = null;
try {
trusted = KeyStore.getInstance("BKS");
} catch (KeyStoreException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
trusted.load(null, "".toCharArray());
MySSLSocketFactory sslf = null;
try {
sslf = new MySSLSocketFactory(trusted);
} catch (KeyManagementException e) {
Log.d(TAG, "Exception " + e);
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
Log.d(TAG, "Exception " + e);
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
Log.d(TAG, "Exception " + e);
// TODO Auto-generated catch block
e.printStackTrace();
}
sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("f_username", "myemail#address.com"));
nameValuePairs.add(new BasicNameValuePair("f_passwd", "mypassword"));
nameValuePairs.add(new BasicNameValuePair("f_method", "LOGIN"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("https", sslf, 443));
SingleClientConnManager cm = new SingleClientConnManager(httppost.getParams(), schemeRegistry);
// NEW API WONT ALLOW THIS IN THE MAIN THREAD! hence ASYNC
DefaultHttpClient client = new DefaultHttpClient(cm, httppost.getParams());
HttpResponse result = client.execute(httppost);
// Check if server response is valid
StatusLine status = result.getStatusLine();
Log.d(TAG, "STatus" + result.getStatusLine());
if (status.getStatusCode() != 200) {
throw new IOException("Invalid response from server: " + status.toString());
}
HttpEntity entity = result.getEntity();
InputStream is = entity.getContent();
if (is != null) {
is.close(); // release connection
}
String phpsessid = "";
// cookies from another blog
// http://stackoverflow.com/questions/4224913/android-session-management
List cookies = client.getCookieStore().getCookies();
if (cookies.isEmpty()) {
Log.d(TAG, "no cookies received");
} else {
for (int i = 0; i < cookies.size(); i++) {
// Log.d(TAG, "COOKIE-" + i + " " +
// cookies.get(i).toString());
if (cookies.get(i).toString().contains("PHPSESSID")) {
phpsessid = cookies.get(i).toString();
Log.d(TAG, "COOKIE FOR PHPSESSID - " + phpsessid);
}
}
} // end of blog
entity.consumeContent();
client.getConnectionManager().shutdown();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (CertificateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return 1;
} // end of postData()
public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
#Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host,
port, autoClose);
}
#Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
I know the url is correct, as are the name value pairs, as I can login via a query string via a browser or via wget:
https://domainname.com/nclogin.submit?f_username=myemail#email.com&f_passwd=password&f_method=LOGIN
This results in a connection established and a redirect to my dashboard page.
The HTML code (source) from the login page can be viewed
here