I want my application to be able to send email on demand. I am currently using the tutorial from www.mykong.com which details setting up gmail settings.
However, I can't get the configuration settings into my annotated spring controllers: I want to avoid using the following:
ApplicationContext context = new FileSystemXmlApplicationContext(email-context.xml");
MailMail mm = (MailMail) context.getBean("mailMail");
mm.send(message);
From my investigation this seems rather frowned upon. I've tried several things, but none of them seem to find the correct bean and produce a nullpointerexception. Is there a way I can add this to any neccessary controllers, e.g. #Property(mailMail) or #Autowired private mailMail? Or should I just move the settings from my email-context into the java itself?
My files are below:
EmailSender.java
public class EmailSender {
#Autowired
private MailSender mailSender;
public void sendMail(String subject, String msg) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("beesden#*.com");
message.setTo("beesden#*.com");
message.setSubject(subject);
message.setText(msg);
mailSender.send(message);
}
}
PageController
#RequestMapping(value = { "/{name}" }, method = RequestMethod.GET)
public String showPage(#PathVariable("name") String name, HttpServletRequest request, Model model) {
logger.debug("Page request: " + name);
mm.sendMail("Hi","Test");
return "webpage";
}
email-context.xml
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="port" value="587" />
<property name="username" value="toby#gmail.com" />
<property name="password" value="tobytobytoby" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
</props>
</property>
</bean>
<bean id="mailMail" class="org.system.EmailSender">
<property name="mailSender" ref="mailSender" />
</bean>
(note I changed the username and password for here, they are correct in the system...)
Many thanks
Related
I have a mail sender set up in config file: spring/servlet-context.xml
which has username and password set.
I've come up with a specific use-case where I need to send mail from a different email account.
Is it possible to set this up in this same config file.
At first, I thought this would mean simply to add another bean id having the other email account's username and password set within, but then that didn't make sense to me how is the JavaMailSender going to tell which sender I want each time?!
My code:
In servlet-context.xml:
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="port" value="587" />
<property name="username" value="default_email#gmail.com" />
<property name="password" value="***1***" />
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.debug">false</prop>
<prop key="mail.smtp.sendpartial">true</prop>
</props>
</property>
</bean>
[ I thought to add here:
<bean id="anotherMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
...
<property name="username" value="another_email#gmail.com" />
<property name="password" value="***2***" />
...
</bean>
]
And a Java Class responsible for email sending:
public class MailService {
private static JavaMailSender mailSender;
#SuppressWarnings("static-access")
public void setMailSender(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void sendMail(final String aSubject, final String aContent, final String toMail, final List<String> attachedFileUrls, String aFilename) {
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true,"UTF-8");
helper.setFrom(simpleMailMessage.getFrom());
helper.setTo(toMail);
helper.setSubject("A subject");
helper.setText("some content", true);
} catch (Exception e) {...}
Thread thread = new SendMail1(message);
thread.start();
}
class SendMail1 extends Thread {
MimeMessage message;
SendMail1(MimeMessage message) {
this.message = message;
}
public void run() {
mailSender.send(message);
}
}
}
(It doesn't help changing setFrom and setTo functions, because they only set the visual "to" and "from" in recipent's mail box)
At the moment mailSender "knows" somehow by the config settings above to send email to the email set in servlet-context.xml .
I would like to add sendMailFromSpecialSender function which will send email from other sender.
Is this possible?
If it is, then how?
UPDATE:
After posting this question I found a partial answer to my question by Bill Shannon:
The simple solution is to use a separate Session for each sender and send each message one at a time.
So...
1. How do I create a separate Session for my other sender case?
2. Does the configuration in servlet-context.xml enable having a separate session with other configuration, or can I leave that as it is?
Thank-you
Your question seems to be about Spring's dependency injection, and how to inject two beans of the same class.
One good way to do this is to use a #Qualifier:
public void setPrimaryMailSender(#Qualifier("primary") JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void setSecondaryMailSender(#Qualifier("secondary") JavaMailSender mailSender) {
this.secondaryMailSender = mailSender;
}
and then in your bean definitions:
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<qualifier value="primary"/>
...
</bean>
<bean id="anotherMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<qualifier value="secondary"/>
...
</bean>
In this way, you can easily inject two fields of the same type.
You just have to use another mailSender in your sendMail() method.
In that method you can have conditional check something like
if(condtion){
MimeMessage=mailSender.createMimeMessage();
else {
MimeMessage=otherSender.createMimeMessage()
}
Similar check in your inner class can help ypu to decide which sender to use.
I have below details in spring xml file. Now I want to convert it into spring java config bean.
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="test" />
<property name="port" value="111" />
<property name="username" value="test#gmail.com" />
<property name="password" value="test123" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
</props>
</property>
</bean>
<bean id="utilityObject" class="com.ezone.utility.TestUtility">
<property name="mailSender" ref="mailSender" />
</bean>
Converted mailSender this bean as below. But How to convert utilityObject in java config spring bean. I am new in this.
#Bean(name="mailSender",autowire=Autowire.BY_NAME)
public JavaMailSenderImpl mailConfiguration(){
JavaMailSenderImpl mail = new JavaMailSenderImpl();
mail.setHost("test");
mail.setPort(111);
mail.setUsername("test#gmail.com");
mail.setPassword("test123");
Properties javaMailProperties = new Properties();
javaMailProperties.put("mail.smtp.auth", "true");
javaMailProperties.put("mail.smtp.starttls.enable", "true");
javaMailProperties.setProperty("mail.smtp.auth", "true");
javaMailProperties.setProperty("mail.smtp.starttls.enable", "true");
mail.setJavaMailProperties(javaMailProperties);
return mail;
}
How can I define below bean :
<bean id="utilityObject" class="com.ezone.utility.TestUtility">
<property name="mailSender" ref="mailSender" />
</bean>
The above bean has the reference of mailSender.
You can either put a parameter on the #Bean method, which will get injected:
#Bean
public TestUtility utilityObject(JavaMailSender mailConfiguration) {
return new TestUtility(mailConfiguration);
}
or call from one #Bean method in an #Configuration to another; Spring will proxy them and make sure the singleton behavior gets applied:
#Bean
public TestUtility utilityObject() {
return new TestUtility(mailConfiguration());
}
I think the first one is a bit less magic, but either approach should work.
The methods annotated with #Bean can be called from other methods. Spring makes proxy for #Configuration class and singletons are created only once.
#Bean
public TestUtility utilityObject() {
TestUtility uo = new TestUtility();
uo.setMailSender(mailConfiguration());
return uo;
}
See details http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-java-further-information-java-config
Use #configuration for the JavaMailSenderImpl class
Refer : http://www.tutorialspoint.com/spring/spring_java_based_configuration.htm
EDIT
#Bean
public TestUtility getUtilityObject() {
return new TestUtility(mailConfiguration());
}
I am new in spring MVC i have got an issue while send email through spring . no exception will occur but mail not send.
my applicationContext.xml
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="username" value="uname" />
<property name="password" value="pass" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.socketFactory.port">465</prop>
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<prop key="mail.smtp.port">465</prop>
</props>
</property>
</bean>
my controller class
#Controller
public class WebController {
// System.out.println("suceees");
#Autowired
private JavaMailSender mailSender;
#RequestMapping(value = "/index", method = RequestMethod.GET)
public String index() {
return "index";
}
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public String redirect() {
sendMail();
return "redirect:finalPage";
}
#RequestMapping(value = "/finalPage", method = RequestMethod.GET)
public String finalPage() {
return "final";
}
public void sendMail() {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom("sender");
helper.setTo("receiver");
helper.setSubject("hi");
helper.setText("welcome");
// attach the file
FileSystemResource file = new FileSystemResource(new File("/home/ajmal/Pictures/messi.jpg"));
helper.addAttachment("messi.jpg", file);//image will be sent by this name
mailSender.send(message);
} catch (MailException | MessagingException ex) {
System.err.println("error");
}
}
}
thanks in advance .. no exception will occur. but mail not send ?
We had into the same problem sometime back, with Spring Boot 1.2.5. Looks like with the latest version of Java Mail, now another property is needed - spring.mail.properties.mail.smtp.ssl.enable to be set as true. See this post for details.
Also, when I tested my application, I saw that merely giving the regular gmail password didn't anymore work. I needed a 2-step verified account, and had to use an application password.
I need to send a letter with the body:
Lector {LectorName} had created a new course
----------------------------------------------------
Name: {CourseName}
Category: {CourseCategory}
Description: {CourseDescription}
Links: {CourseLinks}
----------------------------------------------------
Please, review this course at {CourseApproveLink}
I made on a page freemarker
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<p> ${LectorName} had created a new course</p>
<p>----------------------------------------------------</p>
<p>Name: ${Course.title}</p>
<p>Category: ${Course.category.name}</p>
<p>Description: ${Course.descr}</p>
<p>Links: ${Course.links}</p>
<p>----------------------------------------------------</p>
<p>Please, review this course at ${CourseApproveLink}</p>
</body>
</html>
how to fill it and pass the values in the method of sending the letter?
Here is my code. My method sendMail and Bean "mailSender" with my settings.
It is necessary to do so new MimeMessage(session) ?
How do I get the settings from the bean into the session?
#Service("mailService")
public class MailService {
#Autowired
private MailSender mailSender;
#Autowired
private SimpleMailMessage alertMailMessage;
#Resource(name = "freemarkerEmailConfig")
private Configuration emailConfiguration;
public void sendMail(String from, String to, String subject, String body) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(body);
mailSender.send(message);
}
public void sendAlertMail(String alert) {
SimpleMailMessage mailMessage = new SimpleMailMessage(alertMailMessage);
mailMessage.setText(alert);
mailSender.send(mailMessage);
}
}
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.mail.ru" />
<property name="port" value="465" />
<property name="username" value="user#mail.ru" />
<property name="password" value="***********" />
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.ssl.enable">true</prop>
<prop key="mail.debug">true</prop>
</props>
</property>
</bean>
<bean id="alertMailMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from">
<value>dima4nolimit#mail.ru</value>
</property>
<property name="to">
<value>bizanrus#mail.ru</value>
</property>
<property name="subject"
value="Alert - Exception occurred. Please investigate" />
</bean>
You need to pass in a map to the method that sends email with freemarker template. In your case the map will look something like:
Map<Object, Object> map = new HashMap<Object, Object>();
map.put("LectorName", "...");
map.put("Course", course);
map.put("CourseApproveLink", "...");
Freemarker will resolve variable names based on the keys you passed in.
If you use Spring, then configure the template directory in applicationContext.xml like this:
<!-- FreeMarker Configuration -->
<bean id="freemarkerEmailConfig" class="freemarker.template.Configuration">
<property name="directoryForTemplateLoading" value="templates/email" />
<property name="objectWrapper">
<bean class="freemarker.template.DefaultObjectWrapper"/>
</property>
</bean>
Put your template under templates/email folder (relative to your webapp). Inject the freemarkerEmailConfig bean defined in applicationContext into your service class:
#Resource(name = "freemarkerEmailConfig")
private Configuration emailConfiguration;
Now in your service class you can use emailConfiguration to retrieve the template and then process it with the map above like this:
Template template = emailConfiguration.getEmailTemplate(templateName);
String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
FreeMarkerTemplateUtils is a class from Spring. Now text will contain the html with the all the variables substituted by values from the map. Just send the email with text as html content:
MimeMessage msg = mailSender.createMimeMessage();
msg.setFrom(new InternetAddress(EMAIL_SENDER_ADDRESS, EMAIL_SENDER_PERSONAL));
msg.setSubject(subject);
msg.setSentDate(new Date());
msg.setContent(text, "text/html; charset=UTF-8");
for (EmailInternetAddress emailInternetAddress :emailInternetAddresses) {
msg.addRecipient(emailInternetAddress.getRecipientType(),
emailInternetAddress.getInternetAddress());
}
mailSender.send(msg);
Scenario: User submits contact form with her email address. The email I receive should be "from" the email filled in the contact form. What I get instead is the gmail (foo#gmail.com) account I configured in spring context, although the setFrom is set properly in code as following:
public void sendContactNotification(final ContactForm contactForm) {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
#SuppressWarnings({ "rawtypes", "unchecked" })
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setTo(contact#foo.com);
message.setFrom(contactForm.getEmail());
message.setSubject("New contact message " + contactForm.getTopic());
message.setReplyTo(contactForm.getEmail());
message.setSentDate(new Date());
Map model = new HashMap();
model.put("newMessage", contactForm);
String text = VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine, "velocity/new_contact_message.vm", "UTF-8", model);
message.setText(text, true);
}
};
this.mailSender.send(preparator);
}
In Spring context the sender is configured as following:
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="port" value="587" />
<property name="username" value="foo#gmail.com" />
<property name="password" value="password" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
</props>
</property>
Thanks,
Adrian