I’m working on a java application that needs to send a daily email. I’m using Thymeleaf to build the message body from a template, adding the result to a mime BodyPart, and then setting that part as the content of the message. The goal is to have a table of contents where each item is a link to a section of the message. Unfortunately, when I look at the resulting email in gmail, none of the links work.
I put in some logging and verified that the html is getting generated correctly. In the table of contents I have some html like:
<ul id="titles_6e8c478e-aabe-4789-ab22-8092e19c2dde" style="list-style: none; margin: 0 0 10px 0; padding-left: 15px; font-size: 13px;">
<li><a href="#message_2401_6e8c478e-aabe-4789-ab22-8092e19c2dde">A display test</a></li>
<li><a href="#message_2383_6e8c478e-aabe-4789-ab22-8092e19c2dde">Testing individual</a></li>
</ul>
Where the href is being built based on some id data from the message. Futher down the page the target html looks like:
<table class="message" width="100%" align="center" cellpadding="0" cellspacing="0" border="0" style="border-bottom: solid #ccc 1px;">
<tr>
<td style="font-size: 13px; color: #333333; padding-left: 15px; padding-bottom: 15px; padding-top: 15px;">
<a id="message_2401_6e8c478e-aabe-4789-ab22-8092e19c2dde"></a>
<span ><strong>A display test</strong></span><br/>
<p><a href="#pagetop">Top</a></p>
</td>
</tr>
</table>
<table class="message" width="100%" align="center" cellpadding="0" cellspacing="0" border="0" style="border-bottom: solid #ccc 1px;">
<tr>
<td style="font-size: 13px; color: #333333; padding-left: 15px; padding-bottom: 15px; padding-top: 15px;">
<a id="message_2383_6e8c478e-aabe-4789-ab22-8092e19c2dde"></a>
<span ><strong>Testing individual</strong></span><br/>
<p><a href="#pagetop">Top</a></p>
</td>
</tr>
</table>
So far so good. The problem is, my html is getting modified at some point during the building and sending of the message. When I examine the html of the received email, my href tags are now formatted like:
<a href="#m_-2166845457075511738_message_2401_6e8c478e-aabe-4789-ab22-8092e19c2dde">A display test</a>
Noticed the extra prefix that has been added? By itself this wouldn’t be a problem, but when I look at the target html it now looks like:
<a id="m_-2166845457075511738message_2401_6e8c478e-aabe-4789-ab22-8092e19c2dde"></a>
If they matched, the extra prefix wouldn’t matter, but that missing underscore means that all of these links are now broken.
if it helps, my code responsible for building and sending the email looks like this:
public SimpleResponse sendEmail(List<String> toAddresses, String subject) throws IOException {
Properties prop = new Properties();
prop.put("mail.smtp.host", host);
prop.put("mail.smtp.port", port);
prop.put("mail.smtp.starttls.enable", "true");
prop.put("mail.smtp.auth", "false");
prop.put("mail.smtp.socketFactory.port", port);
prop.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
Session session = Session.getInstance(prop);
Message message = new MimeMessage(session);
Multipart multipart = new MimeMultipart();
try {
logger.info("Attempting to send email, " + subject + " to: " + recipients);
message.setFrom(new InternetAddress("[email protected]"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
message.setSubject(subject);
//generate the html content of the email from a thymeleaf template
String digestHtml = generateDailyDigestFromTemplate(learnerEmail, subscribedMessages);
//this line outputs the html and everything looks as expected
System.out.println(digestHtml);
BodyPart dailyDigestBody = new MimeBodyPart();
dailyDigestBody.setContent(digestHtml, "text/html");
multipart.addBodyPart(bodyPart);
message.setContent(multipart);
Transport.send(message);
} catch (MessagingException e) {
logger.error("Failed to send email", e);
return new SimpleResponse("sendEmail: " + subject, false,
"Failed to sent email to: " + toAddresses + " with error: " + e.getMessage());
}
logger.info("Successfully sent email, " + subject + " to: " + recipients);
return new SimpleResponse("sendEmail: " + subject, true, "Successfully sent email to: " + toAddresses);
}
At this point I’m a bit stuck. Any idea what could be causing this? What do I do to fix it?
UPDATE: I have managed to narrow down the cause of the issue, but I’m still not sure how to fix it. The problem is coming from the gmail client. If I click on the ‘more’ menu and select ‘show original’ the html looks perfectly fine. It’s only when I examine it in the client that the extra text gets added.
2
Answers
I was able to find a workaround, but I still don't have a clear understanding of what is causing this issue. If I use a 'name' attribute in place of 'id' in the target element, the generated prefixes match and my links work. So
would instead look like:
The issue you are facing with your email links having an extra prefix is related to how Gmail modifies the HTML content of your email when rendering it.
To work around this issue and ensure that your links work correctly, you can consider the following options:
Use Absolute URLs:
Instead of using relative anchor links (e.g., href="#message_2401_6e8c478e-aabe-4789-ab22-8092e19c2dde"), you can use absolute URLs. These are complete URLs that include the full address of the target within your email. Gmail is less likely to modify absolute URLs. For example:
Minimize JavaScript and Event Attributes
Avoid using JavaScript-based actions within your email, as this may trigger additional modifications by Gmail. Similarly, minimize the use of event attributes like onclick, which can be problematic in email clients.
If it solves your problem, mark it as an answer. Thank you.