set "start" attribute in content-type for mime multipart/related message in javax.mail api - mime

How can I set start attribute in the content-type for mime multipart/related message?
To be more precise, I want to know how I can set the start attribute for the root attachment in the below example taken from https://www.rfc-editor.org/rfc/rfc6362:
--OUTER-BOUNDARY
Content-type: multipart/related; boundary="INNER-BOUNDARY";
start="<root.attachment>"; type="application/xml"
--INNER-BOUNDARY
Content-type: application/xml
Content-ID: <root.attachment>
[XML DOCUMENT]
--INNER-BOUNDARY
Content-type: application/pdf
Content-ID: <2nd.attachment>
[PDF DOCUMENT]
--INNER-BOUNDARY--
--OUTER-BOUNDARY
I am not able to find it in the javax.mail api. Please help.

I've been struggling with that recently, the code below is the best I could come up with (actually nothing else worked for me):
public class MultipartGenerator {
//Let's assume the static members below
//hold our message parts content
//an the instances of arrays of byte
private static final byte [] ROOT_BYTES = new byte[]{/* ... bytes ... */};
private static final byte [] ATTCH_1_BYTES = new byte[]{/* ... bytes ... */};
private static final byte [] ATTCH_2_BYTES = new byte[]{/* ... bytes ... */};
/**
* Generate multipart with headers
*
* #return javax.mail.Multipart instance
*/
public static Multipart generateMultipart() {
//This is our root MimeBodyPart,
//content-id equals 'rootcid'
//content-type equals 'roottype/rootsubtype'
InternetHeaders ih0 = new InternetHeaders();
ih0.addHeader("Content-Type", "roottype/rootsubtype");
ih0.addHeader("Content-Transfer-Encoding", "binary");
ih0.addHeader("Content-ID", "rootcid");
MimeBodyPart rootBodyPart = new MimeBodyPart(ih0, ROOT_BYTES);
//This is a body part wrapping first message attachment
InternetHeaders ih1 = new InternetHeaders();
ih1.addHeader("Content-Type", "text/plain; name=attachment1.txt");
ih1.addHeader("Content-Transfer-Encoding", "binary");
ih1.addHeader("Content-Location", "attachment1.txt");
ih1.addHeader("Content-ID", "a00");
MimeBodyPart attch1BodyPart = new MimeBodyPart(ih1, ATTCH_1_BYTES);
//This is a body part wrapping second message attachment
InternetHeaders ih2 = new InternetHeaders();
ih2.addHeader("Content-Type", "text/plain; name=attachment2.txt");
ih2.addHeader("Content-Transfer-Encoding", "binary");
ih2.addHeader("Content-Location", "attachment2.txt");
ih2.addHeader("Content-ID", "a01");
MimeBodyPart attch2BodyPart = new MimeBodyPart(ih2, ATTCH_2_BYTES);
//This is our desired multipart, this is where things turn a bit dirty
//No success with setting the parameters in a different way
Multipart multipart = new MimeMultipart("related;start=\"<rootcid>\";type=\"roottype/rootsubtype\"");
multipart.addBodyPart(rootBodyPart,0);
multipart.addBodyPart(attch1BodyPart);
multipart.addBodyPart(attch2BodyPart);
return multipart;
}
}
There's probably a better way to handle this task, however I am not able to find one.

Related

I use springBoot And Vue , i want send a response to vue , But response always is garbled

#Controller
#Slf4j
public class SeckillGoodsController {
#Autowired
RedisTemplate redisTemplate;
#GetMapping("/captcha")
public void verifyCode(Long userId,Long goodsId, HttpServletResponse response){
//set Header as pic
response.setContentType("image/gif");
// no cookie keep every flush is new captcha
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("utf-8");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);//never expires
//Use a util [enter image description here][1]
ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 32, 3);
redisTemplate.opsForValue().set("captcha:"+userId+":"+goodsId,captcha.text(),60, TimeUnit.SECONDS);
try {
System.out.println(response.getOutputStream().toString());
captcha.out(response.getOutputStream());
} catch (IOException e) {
log.error("Errot",e.getMessage());
}
}
}
I send a response to vue.js but use postman test the Body always is captcha, I've set the UTF-8, but it's still wrong
[1]: https://i.stack.imgur.com/04RKS.png
this has nothing to do with Spring Boot.
I'm not entirely sure what the ArithmeticCaptcha does but I guess it creates an image and stream it to the response stream
I don't know what you would expect... You are sending binary data (an image) so it is quite normal that you can't read it.
You are setting the content type twice. You can't do that. In addition, it seems to be png so you might want to check it out.
I guess that you want to would like to get a JSON back or similar. In that case, you need to change your code
Here is an example:
#ResponseBody
#RequestMapping("/captcha")
public JsonResult captcha(Long userId, Long goodsId, HttpServletResponse response) throws Exception {
ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 32, 3);
String key = "captcha:"+userId+":"+goodsId
redisTemplate.opsForValue().set(key, captcha.text(), 60, TimeUnit.SECONDS);
return JsonResult.ok().put("key", key).put("image", captcha.toBase64());
}
Might need some tweaks to fit 100% your case but this will return a json with a key that is the one you probably will need to match in your next step and the image base64 encoded so it would be (almost) readable.
You can then add the base64 encoded string from the response as the src of your img tag.

for GET Rest api call using spring-integration, how to read user defined headers?

MessageHeaders has predefined headers like TIMESTAMP, ERROR_CHANNEL etc. but how to access user defined header?
My api has http://localhost:8082/load/1234567?source=ABC and headers like username:testuser
message.getPayload() gives me just this 1234567 so that header is not part of payload, but
Map<String, Object> headers = new HashMap<String, Object>();
Set<String> keys = message.getHeaders().keySet();
MessageHeaders msgHeader = message.getHeaders();
for(String key : keys) {
headers.put(key, msgHeader.get(key));
}
& headers.get("username") returns null.
could someone please help?
I hope that you mean you set a username HTTP header in request.
The HTTP Inbound Channel Adapter (or Gateway) come with a DefaultHttpHeaderMapper by default. This one does only standard HTTP Request headers mapping by default:
private static final String[] HTTP_REQUEST_HEADER_NAMES =
{
HttpHeaders.ACCEPT,
HttpHeaders.ACCEPT_CHARSET,
HttpHeaders.ACCEPT_ENCODING,
HttpHeaders.ACCEPT_LANGUAGE,
HttpHeaders.ACCEPT_RANGES,
HttpHeaders.AUTHORIZATION,
HttpHeaders.CACHE_CONTROL,
HttpHeaders.CONNECTION,
HttpHeaders.CONTENT_LENGTH,
HttpHeaders.CONTENT_TYPE,
HttpHeaders.COOKIE,
HttpHeaders.DATE,
HttpHeaders.EXPECT,
HttpHeaders.FROM,
HttpHeaders.HOST,
HttpHeaders.IF_MATCH,
HttpHeaders.IF_MODIFIED_SINCE,
HttpHeaders.IF_NONE_MATCH,
HttpHeaders.IF_RANGE,
HttpHeaders.IF_UNMODIFIED_SINCE,
HttpHeaders.MAX_FORWARDS,
HttpHeaders.PRAGMA,
HttpHeaders.PROXY_AUTHORIZATION,
HttpHeaders.RANGE,
HttpHeaders.REFERER,
HttpHeaders.TE,
HttpHeaders.UPGRADE,
HttpHeaders.USER_AGENT,
HttpHeaders.VIA,
HttpHeaders.WARNING
};
To include your custom header into a message this channel adapter produces, you just need to incorporate this configuration option:
/**
* Provide the pattern array for request headers to map.
* #param patterns the patterns for request headers to map.
* #return the current Spec.
* #see DefaultHttpHeaderMapper#setOutboundHeaderNames(String[])
*/
public S mappedRequestHeaders(String... patterns) {
and use, for example, just * to map all the headers, or if your requirements are strict only for your headers, then pass their names over there.
See more info in docs: https://docs.spring.io/spring-integration/docs/current/reference/html/http.html#http-header-mapping

How do I stream multiple multipart messages of different mimetypes in spring?

I'm currently using Springs ResponseBodyEmitter to stream a multipart/related response consisting of multiple parts (of mimetype application/json as well as application/octet-stream) to a client. Therefore I am manually setting the boundary in the Content-Type header as well as creating the encapsulation boundaries between the different message parts within the payload. I'm pretty sure there is a more convenient way to achieve this. What would be the idiomatic way in Spring to achieve this?
#GetMapping(value = "/data", produces = {MediaType.MULTIPART_FORM_DATA_VALUE})
public ResponseEntity<ResponseBodyEmitter> streamMultipart() {
// omitting actual contents for the sake of brevity
InputStream audio = new ByteArrayInputStream(null); //asynchronously retrieved
String json = "{}";
ResponseBodyEmitter speakEmitter = new ResponseBodyEmitter();
executor.execute(() -> {
try {
speakEmitter.send("\r\n--myBoundary\r\n");
speakEmitter.send("Content-Type: application/json;\r\n\r\n");
speakEmitter.send(json, MediaType.APPLICATION_JSON);
speakEmitter.send("\r\n--myBoundary\r\n");
speakEmitter.send("Content-Type: application/octet-stream;\r\n\r\n");
speakEmitter.send(audio.readAllBytes(), MediaType.APPLICATION_OCTET_STREAM);
speakEmitter.send("\r\n--myBoundary--\r\n");
} catch (IOException ignoredForBrevity) {}
});
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_TYPE, "multipart/related; boundary=myBoundary");
return ResponseEntity.ok().headers(responseHeaders).body(speakEmitter);
}

Javamail Content-Type

I'm trying to send an Email via javamail adding embedded Images and an Outlook Invation which should be displayed showing up the buttons to accept/decline .... To make the buttons show up, i have to set the Content-Type of the MimeMultipart to related.
MimeMultipart multipart = new MimeMultipart("related");
Once this is done, the embedded Pictures wont show up again.
To Display the embedded images it should be alternative.
I have send myself a Mail from Outlook containing an Image as well as a invation to a meeting.
When I check the header there, it says:
Content-Type: multipart/related;
boundary="_005_CCF531A072806F489D02A6DD2CF322A01D88EEA2de35s004hst42wp_";
type="multipart/alternative"
I have already tried to set the Content-Type adding Parameters (type, charset ...) but it seems like their just getting ignored when sending the message. Here is the Method which I am calling to create the Message Part:
private Message generateMessage() throws Exception
{
Configuration conf = Configuration.getInstance();
// Get system properties
Properties props = System.getProperties();
// Setup mail server
props.put("mail.smtp.host", conf.getProperty(Configuration.MAIL_SERVER));
// Get session
Session session = Session.getDefaultInstance(props, null);
// Create the message
Message message = new MimeMessage(session);
// Fill its headers
message.setSubject(this.subject);
message.setFrom(new InternetAddress(fromEmail));
Address[] replyTo = new Address[]{new InternetAddress(replyEmail)};
message.setReplyTo(replyTo);
// Create a related multi-part to combine the parts
MimeMultipart multipart = new MimeMultipart("related");
// Create your new message part
BodyPart messageBodyPart = new MimeBodyPart();
multipart.addBodyPart(messageBodyPart);
// ADD IMAGES
multipart = attachImages(multipart);
// ADD CALENDAR-FILE
multipart = attachCalendarFile(multipart);
// Set Content-Type
ContentType ct = new ContentType(message.getContentType());
ct.setParameter("charset", "utf-8");
ct.setParameter("type", "multipart/alternative");
// Set Multipart-Content to Message including the Content-Type
message.setContent(multipart, ct.toString());
return message;
}
The output of message.writeTo(System.out); is the following:
From: mail#sender.com
Reply-To: noreply#recipient.com
Message-ID: <1150322817.1.1397725164700.JavaMail.User#MacBooks-mailserver.local>
Subject: test
MIME-Version: 1.0
Content-Type: multipart/related;
boundary="----=_Part_0_72769750.1397725164655"
------=_Part_0_72769750.1397725164655
Is there any chance to make it work with embedded images AND invations?
Thanks in advance!
There's three types of multiparts, each used for a different purpose. In some cases you might need to use all three. For example, a message with a calendar attachment, html content using images, and equivalent plain text content, might have a structure such as this:
multipart/mixed
multipart/alternative
text/plain
multipart/related
text/html
image/jpeg
text/calendar
Google search led me here, so for future searchers:
#bill-shannon is of course correct. However, please save yourself the trouble of figuring out the low level Mime RFC stuff, and just use something like Simple Java Mail (open source) which figures out which structure suits best based on the input you provide. You can interactively explore all the possible structures Simple Java Mail can come up with. Disclaimer: I maintain this library (but I actually came across this SO question in my research into including voting buttons in emails for Outlook :) )
In your case you would use the following. First produce a Calendar content string, using something like ical4j:
Calendar icsCalendar = new Calendar();
icsCalendar.getProperties().add(new ProdId("-//Events Calendar//iCal4j 1.0//EN"));
icsCalendar.getProperties().add(Version.VERSION_2_0);
(..) // add attendees, organizer, end/start date and whatever else you need
// Produce calendar string
ByteArrayOutputStream bOutStream = new ByteArrayOutputStream();
new CalendarOutputter().output(icsCalendar, bOutStream);
String yourICalEventString = bOutStream.toString("UTF-8")
Then use Simple Java Mail's email builder to set the Calendar content alongside everything else such as images:
Email email = EmailBuilder
.startingBlank()
.withCalendarText(CalendarMethod.REQUEST, yourICalEventString)
.everythingElseLikeImagesHeadersAttachmentsEtcEtc()
.buildEmail();
Then send using the mailer builder:
MailerBuilder
.withSMTPServer("server", 25, "username", "password")
.buildMailer()
.sendMail(email);
Then depending on whether you provided text, html attachments or other things, Simple Java Mail will select the appropriate Mime structure with mixed/related/alternative parts.

Jersey:Returning a Response with a Map containing Image Files and JSON String values

I am using Jersey JAX-RS.
I want to return a Response with a Map containing Image Files and JSON String values.
Is this the right way to do this:
Map<String,Object> map = new HashMap........
GenericEntity entity = new GenericEntity<Map<String,Object>>(map) {};
return Response.ok(entity).build();
Or is this better.I plan to use JAX-RS with Jersey only.
JResponse.ok(map).build();
I am basing this on this article:
http://aruld.info/handling-generified-collections-in-jersey-jax-rs/
I am not sure what to specify for #Produces too(planning to leave it out).
TIA,
Vijay
You better produce a multipart response:
import static com.sun.jersey.multipart.MultiPartMediaTypes.MULTIPART_MIXED_TYPE;
import static javax.ws.rs.core.MediaType.APPLICATION_XML_TYPE
#GET
#Produces(MULTIPART_MIXED_TYPE)
public Response get()
{
FileDataSource image = ... (gets the image file)
String info = ... (gets the xml structured information)
MultiPart multiPart = new MultiPart().
bodyPart(new BodyPart(info, APPLICATION_XML_TYPE)).
bodyPart(new BodyPart(image, new MediaType("image", "png")));
return Response.ok(multiPart, MULTIPART_MIXED_TYPE).build();
}
This example was taken from there.

Resources