JavaMail API - Send Emoji/Smiley with Freemarker Template? - spring

I developed rest API in spring.
I have to send invitation mail to user with Emoji.
I developed .ftl and .java configuration file is as follows:
invitation.ftl
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
//Content
</body>
</html>
webAppConfi.java
#Bean
public FreeMarkerConfigurationFactoryBean freeMarkerConfigurationFactoryBean() {
FreeMarkerConfigurationFactoryBean freeMarkerConfigurationFactoryBean = new FreeMarkerConfigurationFactoryBean();
freeMarkerConfigurationFactoryBean
.setTemplateLoaderPath("/WEB-INF/templates/mail/");
freeMarkerConfigurationFactoryBean.setDefaultEncoding("UTF-8");
return freeMarkerConfigurationFactoryBean;
}
sendMail.java
MimeMessage message = null;
MimeMessageHelper objHelper = null;
String strBody = null;
try {
strBody = FreeMarkerTemplateUtils.processTemplateIntoString(
freemarkerMailConfiguration.getTemplate(templetName),
templateProp);
message = this.mailSender.createMimeMessage();
objHelper = new MimeMessageHelper(message, true);
objHelper.setTo(to);
objHelper.setText(strBody, true);
objHelper.setSubject(subject);
mailSender.send(message);
}
finally{}
I get the string like that from iPhone \ud83d\ude14\ud83d\ude17.
So how could i send this emoji value to email body part?
Thank you!

Related

Bootsrap not working with spring boot thymeleaf pdf template

I have a problem adding bootstrap into my thymeleaf template. I want to export that template as pdf.
Bootsrap is not applied to my template. I tried webjars and static bootsrap js and css files but it doesn't work. Is there any other way that i can do? These are webjars links that I have added inside html;
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" th:href="#{webjars/bootstrap/css/bootstrap.min.css}" type="text/css"/>
<script th:src="#{webjars/bootstrap/js/bootstrap.min.js}"></script>
<script th:src="#{webjars/jquery/jquery.min.js}"></script>
</head>
This is java code;
public byte[] getReportByTestId(Long testId, String templateName) throws IOException, DocumentException {
Optional<Test> test = testRepository.findById(testId);
if (test.isPresent()) {
Test _test = test.get();
ObjectMapper oMapper = new ObjectMapper();
Map map = oMapper.convertValue(_test, Map.class);
Context context = new Context();
context.setVariables(map);
String htmlContentToRender = templateEngine.process(templateName, context);
String xHtml = xhtmlConvert(htmlContentToRender);
ITextRenderer renderer = new ITextRenderer();
String baseUrl = FileSystems
.getDefault()
.getPath("src", "main", "resources", "templates")
.toUri()
.toURL()
.toString();
renderer.setDocumentFromString(xHtml, baseUrl);
renderer.layout();
ByteOutputStream outputStream = new ByteOutputStream();
renderer.createPDF(outputStream);
byte[] pdfAsBytes = outputStream.getBytes();
outputStream.close();
return pdfAsBytes;
}
return null;
}
private String xhtmlConvert(String html) throws UnsupportedEncodingException {
Tidy tidy = new Tidy();
tidy.setInputEncoding("UTF-8");
tidy.setOutputEncoding("UTF-8");
tidy.setXHTML(true);
ByteArrayInputStream inputStream = new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
tidy.parseDOM(inputStream, outputStream);
return outputStream.toString("UTF-8");
}
When I add like this;
<script th:src="#{../static/vendor/bootstrap5/bootstrap.min.js}"></script>
It partially works. Only colors are applied.
Thanks for any help.

MimeMessageHelper Spring boot to send email

I am using spring boot to sent an email. Code snippet from my email service
private #Autowired JavaMailSender mailSender;
AND
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED, StandardCharsets.UTF_8.name());
helper.setTo(bo.getToEmails().parallelStream().toArray(String[]::new));
helper.setBcc(bo.getBccEmails().parallelStream().toArray(String[]::new));
helper.setCc(bo.getCcEmails().parallelStream().toArray(String[]::new));
helper.setText(htmlBody, true);
helper.setText(textBody, false);
helper.setSubject(bo.getSubject());
helper.setFrom(new InternetAddress(bo.getFromEmail(),bo.getSenderLabel()));
First I set the htmlBody and then textBody
helper.setText(htmlBody, true);
helper.setText(textBody, false);
it override htmlBody to textBody . How can I send both text and html body using org.springframework.mail.javamail.MimeMessageHelper; any update ?
You can use thymeleaf as your HTML template engine.
Sample HTML code:
MySampleHTML.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>Sample Email</title>
</head>
<body>
<div th:text="${sampleText}"></div>
</body>
<html>
Sample Java Code:
public class EmailSample {
#Autowired
private JavaMailSender mailSender;
#Autowired
private TemplateEngine templateEngine; // From Thymeleaf
public void initiateEmailSend() {
String processedHTMLTemplate = this.constructHTMLTemplate();
// Start preparing the email
MimeMessagePreparator preparator = message -> {
MimeMessageHelper helper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED, "UTF-8");
helper.setFrom("Sample <sample#example.com>");
helper.setTo("recipient#example.com");
helper.setSubject("Sample Subject");
helper.setText(processedHTMLTemplate, true);
};
mailSender.send(preparator); //send the email
}
// Fills up the HTML file
private String constructHTMLTemplate() {
Context context = new Context();
context.setVariable("sampleText", "My text sample here");
return templateEngine.process("MySampleHTML", context);
}
}
And include thymeleaf on your pom.xml
<!-- For email HTML templating -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
NOTE: Put the MySampleHTML.html file on resources/templates/ folder for thymeleaf to see it.
instead of
helper.setText(htmlBody, true);
helper.setText(textBody, false);
Use
helper.setText(htmlBody, textBody);

can we modify method for error handling with status codes?

I'm working on a Spring Boot project. I'm checking out the code with class named ExceptionHandlerController provided at this post and tried it in my project. It works, but for errors with status codes 400 or 500 series I need to include the status code. When I try a simple invalid url in the browser address field, the view page, error.jsp, does render but the status code is not being accessed based on the model information. I've included the HttpServletResponse parameter to obtain the status code, but the code and message doesn't show on a 404 error. The defaultErrorHanddler method doesn't even fire on a 404 error. How do we force the method to fire on 400 and 500 errors?
ExceptionHandlerController:
#ControllerAdvice
public class ExceptionHandlerController
{
public static final String DEFAULT_ERROR_VIEW = "error";
private static final HashMap<Integer, String> statusCodes = new HashMap<Integer, String>();
static {
statusCodes.put(HttpServletResponse.SC_OK, "OK");
statusCodes.put(HttpServletResponse.SC_CREATED, "Created");
statusCodes.put(HttpServletResponse.SC_ACCEPTED, "Accepted");
statusCodes.put(HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION, "Non-authoritative Information");
statusCodes.put(HttpServletResponse.SC_NO_CONTENT, "No Content");
statusCodes.put(HttpServletResponse.SC_RESET_CONTENT, "Reset Content");
statusCodes.put(HttpServletResponse.SC_PARTIAL_CONTENT, "Partial Content");
statusCodes.put(HttpServletResponse.SC_BAD_REQUEST, "Bad Request");
statusCodes.put(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
statusCodes.put(HttpServletResponse.SC_PAYMENT_REQUIRED, "Payment Required");
statusCodes.put(HttpServletResponse.SC_FORBIDDEN, "Forbidden");
statusCodes.put(HttpServletResponse.SC_NOT_FOUND, "Not Found");
statusCodes.put(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method Not Allowed");
statusCodes.put(HttpServletResponse.SC_NOT_ACCEPTABLE, "Not Acceptable");
statusCodes.put(HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required");
statusCodes.put(HttpServletResponse.SC_REQUEST_TIMEOUT, "Request Timeout");
statusCodes.put(HttpServletResponse.SC_CONFLICT, "Conflict");
statusCodes.put(HttpServletResponse.SC_GONE, "Gone");
statusCodes.put(HttpServletResponse.SC_LENGTH_REQUIRED, "Length Required");
statusCodes.put(HttpServletResponse.SC_PRECONDITION_FAILED, "Precondition Failed");
statusCodes.put(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, "Request entity Too Large");
statusCodes.put(HttpServletResponse.SC_REQUEST_URI_TOO_LONG, "Request-URI Too Long");
statusCodes.put(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
statusCodes.put(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, "Requested Range Not Satisfiable");
statusCodes.put(HttpServletResponse.SC_EXPECTATION_FAILED, "Expectation Failed");
statusCodes.put(HttpServletResponse.SC_PRECONDITION_FAILED, "Precondition Required");
statusCodes.put(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
statusCodes.put(HttpServletResponse.SC_NOT_IMPLEMENTED, "Not Implemented");
statusCodes.put(HttpServletResponse.SC_BAD_GATEWAY, "Bad Gateway");
statusCodes.put(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Service Unavailable");
statusCodes.put(HttpServletResponse.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
statusCodes.put(HttpServletResponse.SC_HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported");
}
#ExceptionHandler(value={Exception.class, RuntimeException.class})
public ModelAndView defaultErrorHanddler(HttpServletRequest request, Exception e, HttpServletResponse response)
{
ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);
int scode = response.getStatus();
System.out.println("scode: " + scode);
mav.addObject("statuscode", String.valueOf(scode));
mav.addObject("message", statusCodes.get(scode));
mav.addObject("datetime", new Date());
mav.addObject("exception", e);
mav.addObject("url", request.getRequestURL());
return mav;
}
}
error.jsp:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML>
<html>
<head>
<title></title>
...
</head>
<body>
<div class="container">
<h1>Error Details</h1>
<p>Status Code: ${statuscode}</p>
<p>Message: ${message}</p>
<p>TimeStamp: ${datetime}</p>
<p>Exception: ${exception}</p>
<p>URL: ${url}</p>
<p>Home Page</p>
</div>
</body>
</html>
Alternatively you can annotate your method with #ResponseStatus, for example:
#ResponseStatus(HttpStatus.BAD_REQUEST)
#ExceptionHandler(value = {Exception.class, RuntimeException.class})
public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);
mav.addObject("datetime", new Date());
mav.addObject("exception", e);
mav.addObject("url", request.getRequestURL());
return mav;
}
Add HttpServletResponse as a parameter to defaultErrorHandler method and call response.setStatusCode.
Edit:
For 404 to be treated as an exception, if using Spring Boot, set spring.mvc.throwExceptionIfNoHandlerFound = true. If not using Spring Boot, see this thread.

Why the value in model.put is appended in URL

I am building a Spring MVC Web App. In one Controller, I used model.put method to pass some information to a jsp file.
The following is the snippet of controller
#RequestMapping(value = "/login" , method= RequestMethod.POST)
public String loginPost(HttpSession session,ModelMap model, #RequestParam(value = "username") String username, #RequestParam(value = "password") String password) throws Exception {
User user = getUser(username, password);
if(user !=null){
session.setAttribute("username",username);
model.put("message","login successful ");
return "redirect:/index";
}else{
model.put("message","login failed");
return "redirect:/login";
}
}
The index.jsp and login.jsp:
<%# page contentType="text/html; charset=UTF-8" %>
<html>
<body>
Click to upload page
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: cbl
Date: 2016/1/6
Time: 15:34
To change this template use File | Settings | File Templates.
--%>
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>${message}</h1>
<form method = "POST" action = "/login">
<label for="username">Username</label>
<input id="username" type="text" name = "username">
<label for="password">Password</label>
<input id="password"type="password" name="password">
<input type="submit" value="login">
</form>
</body>
</html>
The ${message} is extected to be display within body, however, it is appended after URl:http://localhost:8000/login?message=login+failed and http://localhost:8000/index?message=login+successful++
Any response is appreciated
Since you are returning a redirect, a new GET request is created under the covers, that is why is getting attached to the url.
If you want to keep the data in the model only, you can use the flash scope with RedirectAttributes
#RequestMapping(value = "/login" , method= RequestMethod.POST)
public String loginPost(HttpSession session,
RedirectAttributes ra,
#RequestParam(value = "username") String username,
#RequestParam(value = "password") String password) throws Exception {
User user = getUser(username, password);
if(user !=null){
session.setAttribute("username",username);
ra.addFlashAttribute("message","login successful ");
return "redirect:/index";
}else{
ra.addFlashAttribute("message","login failed");
return "redirect:/login";
}
}

Arabic is displayed as ????? in velocity template

Greetings all
i am using velocity templates in sending emails
and in the template i have some arabic texts
and when sending the email, the text appears like ??????????
i don't know why:
encoding is set to utf-8 before sending the email here:
VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,templateName, "UTF-8",newModel);
i tried to add the charset in the vm, but with no luck:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
any ideas why such problem occurs ?
I was able to produce Arabic text (تجاوز سعة مكدس) on a plain-text email sent from a Spring app. The text displayed properly on GMail as well as Thunderbird. Here's my mail sending logic:
public void send(String fromAddress, String fromName,
String toAddress, String subject,
String template, Map<String, Object> model) {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(
mimeMessage, "UTF-8");
message.setTo(toAddress);
message.setFrom(new InternetAddress(fromAddress, fromName));
message.setSubject(subject);
message.setText(VelocityEngineUtils
.mergeTemplateIntoString(velocityEngine, template, "UTF-8",
model));
}
};
mailSender.send(preparator);
}
Do you have any velocity.properties set? (particularly input.encoding or output.encoding) If not, try setting those both to UTF-8 also.

Resources