Created
September 5, 2023 20:53
-
-
Save stickfigure/848b4c6728ea76847abb169b3d341d1d to your computer and use it in GitHub Desktop.
Java code to convert data: urls in html email to multipart/related mime messages with content id links
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.orbitkit.blah.blah; | |
import com.google.common.base.Preconditions; | |
import com.google.common.io.BaseEncoding; | |
import lombok.SneakyThrows; | |
import lombok.Value; | |
import lombok.With; | |
import javax.mail.Session; | |
import javax.mail.internet.MimeBodyPart; | |
import javax.mail.internet.MimeMessage; | |
import javax.mail.internet.MimeMultipart; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class ImageReplacer { | |
@Value @With | |
public static class Replaced { | |
/** With data: urls replaced by cids */ | |
String message; | |
/** The resulting image parts, with unique cids */ | |
List<ImagePart> images; | |
@SneakyThrows | |
public MimeMessage toMimeMessage() { | |
final MimeMessage mimeMessage = new MimeMessage((Session)null); | |
final MimeMultipart multipartRelated = new MimeMultipart("related"); | |
mimeMessage.setContent(multipartRelated); | |
final MimeBodyPart htmlPart = new MimeBodyPart(); | |
htmlPart.setContent(message, "text/html; charset=utf-8"); | |
multipartRelated.addBodyPart(htmlPart); | |
for (final ImagePart image : images) { | |
final byte[] imageBytes = BaseEncoding.base64().decode(image.getBase64()); | |
final MimeBodyPart imagePart = new MimeBodyPart(); | |
imagePart.setContentID(image.getCid()); | |
imagePart.setContent(imageBytes, image.getContentType()); | |
multipartRelated.addBodyPart(imagePart); | |
} | |
return mimeMessage; | |
} | |
} | |
@Value | |
public static class ImagePart { | |
String cid; | |
String contentType; | |
String base64; | |
} | |
public static Replaced replace(final String message) { | |
final StringBuilder bld = new StringBuilder(); | |
final List<ImagePart> images = new ArrayList<>(); | |
int here = 0; | |
while (true) { | |
final int blockStart = message.indexOf("src=\"data:", here); | |
if (blockStart < 0) { | |
break; | |
} | |
final int dataStart = blockStart + "src=\"".length(); | |
// Everything up to the start of the data url | |
bld.append(message, here, dataStart); | |
final int dataEnd = message.indexOf("\"", dataStart); | |
Preconditions.checkState(dataEnd > dataStart); | |
final String dataUrl = message.substring(dataStart, dataEnd); | |
final ImagePart part = partFromDataUrl(dataUrl, images.size()); | |
images.add(part); | |
bld.append("cid:").append(part.getCid()).append('"'); | |
here = dataEnd + 1; | |
} | |
bld.append(message, here, message.length()); | |
return new Replaced(bld.toString(), images); | |
} | |
private static ImagePart partFromDataUrl(final String dataUrl, final int imageIndex) { | |
final String[] splitProtocol = dataUrl.split(":"); | |
Preconditions.checkArgument(splitProtocol.length == 2); | |
Preconditions.checkArgument(splitProtocol[0].equals("data")); | |
final String startsWithContentType = splitProtocol[1]; | |
final String[] splitContentType = startsWithContentType.split(";"); | |
Preconditions.checkArgument(splitContentType.length == 2); | |
final String contentType = splitContentType[0]; | |
final String startsWithBase64 = splitContentType[1]; | |
final String[] splitBase64 = startsWithBase64.split(","); | |
Preconditions.checkArgument(splitBase64.length == 2); | |
Preconditions.checkArgument(splitBase64[0].equals("base64")); | |
final String base64Data = splitBase64[1]; | |
return new ImagePart("image" + imageIndex, contentType, base64Data); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment