JavaMail MIME attachment link by cid - ios

Background
I have banged my head against this for a while and not made much progress. I am generating MPEG_4 / AAC files in Android and sending them by email as .mp3 files. I know they aren't actually .mp3 files, but that allows Hotmail and Gmail to play them in Preview. They don't work on iPhone though, unless they are sent as .m4a files instead which breaks the Outlook / Gmail Preview.
So I have thought of a different approach which is to attach as a .mp3 file but have an HTML link in the email body which allows the attached file to be downloaded and specifies a .m4a file name. Gmail / Outlook users can click the attachment directly whereas iPhone users can use the HTML link.
Issue
I can send an email using JavaMail with HTML in it including a link which should be pointing at the attached file to allow download of that file by the link. Clicking on the link in Gmail (Chrome on PC) gives a 404 page and iPhone just ignores my clicking on the link.
Below is the code in which I generate a multipart message and assign a CID to the attachment which I then try to access using the link in the html part. It feels like I am close, but maybe that is an illusion. I'd be massively grateful if someone could help me fix it or save me the pain if it isn't possible.
private int send_email_temp(){
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", smtp_host_setting);
//props.put("mail.debug", "true");
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.port", smtp_port_setting);
session = Session.getInstance(props);
ActuallySendAsync_temp asy = new ActuallySendAsync_temp(true);
asy.execute();
return 0;
}
class ActuallySendAsync_temp extends AsyncTask<String, String, Void> {
public ActuallySendAsync_temp(boolean boo) {
// something to do before sending email
}
#Override
protected Void doInBackground(String... params) {
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(recipient_email_address));
message.setSubject(email_subject);
Multipart multipart = new MimeMultipart();
MimeBodyPart messageBodyPart = new MimeBodyPart();
String file = mFileName;
/**/
DataSource source = new FileDataSource(file);
messageBodyPart.setDataHandler(new DataHandler(source));
/* /
File ff = new File(file);
try {
messageBodyPart.attachFile(ff);
} catch(IOException eio) {
Log.e("Message Error", "Old Macdonald");
}
/* /
messageBodyPart = new PreencodedMimeBodyPart("base64");
byte[] file_bytes = null;
File ff = new File(file);
try {
int length = (int) ff.length();
BufferedInputStream reader = new BufferedInputStream(new FileInputStream(ff));
file_bytes = new byte[length];
reader.read(file_bytes, 0, length);
reader.close();
} catch (IOException eio) {
Log.e("Message Error", "Old Macdonald");
}
messageBodyPart.setText(Base64.encodeToString(file_bytes, Base64.DEFAULT));
messageBodyPart.setHeader("Content-Transfer-Encoding", "base64");
/**/
messageBodyPart.setFileName( DEFAULT_AUDIO_FILENAME );//"AudioClip.mp3");
//messageBodyPart.setContentID("<audio_clip>");
String content_id = UUID.randomUUID().toString();
messageBodyPart.setContentID("<" + content_id + ">");
messageBodyPart.setDisposition(Part.ATTACHMENT);//INLINE);
messageBodyPart.setHeader("Content-Type", "audio/mp4");
multipart.addBodyPart(messageBodyPart);
MimeBodyPart messageBodyText = new MimeBodyPart();
//final String MY_HTML_MESSAGE = "<h1>My HTML</h1><a download=\"AudioClip.m4a\" href=\"cid:audio_clip\">iPhone Download</a>";
final String MY_HTML_MESSAGE = "<h1>My HTML</h1><a download=\"AudioClip.m4a\" href=\"cid:" + content_id + "\">iPhone Download</a>";
messageBodyText.setContent( MY_HTML_MESSAGE, "text/html");
multipart.addBodyPart(messageBodyText);
message.setContent(multipart);
Print_Message_To_Console(message);
Transport transport = session.getTransport("smtp");
transport.connect(smtp_host_setting, username, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
} catch (MessagingException e) {
e.printStackTrace();
} finally {
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// something to do after sending email
}
}
int Print_Message_To_Console(Message msg) {
int ret_val = 0;
int line_num = 0;
InputStream in = null;
InputStreamReader inputStreamReader = null;
BufferedReader buff_reader = null;
try {
in = msg.getInputStream();
inputStreamReader = new InputStreamReader(in);
buff_reader = new BufferedReader(inputStreamReader);
String temp = "";
while ((temp = buff_reader.readLine()) != null) {
Log.d("Message Line " + Integer.toString(line_num++), temp);
}
} catch(Exception e) {
Log.d("Message Lines", "------------ OOPS! ------------");
ret_val = 1;
} finally {
try {
if (buff_reader != null) buff_reader.close();
if (inputStreamReader != null) inputStreamReader.close();
if (in != null) in.close();
} catch(Exception e2) {
Log.d("Message Lines", "----------- OOPS! 2 -----------");
ret_val = 2;
}
}
return ret_val;
}

You need to create a multipart/related and set the main text part as the first body part.

Related

How to Upload a Profile photo in base64 format For Community Users Using ConnectApi.UserProfiles.setPhoto

1Am Uploading Profile Photo for Community Users in base64 format By Using ConnectApi.UserProfiles.setPhoto Method. But am getting "ConnectApi.ConnectApiException: The file you uploaded doesn't appear to be a valid image" This error, Help me to Fix this issue.
Hi you can try the below method:
public PageReference upload() {
Blob b;
document.AuthorId = UserInfo.getUserId();
document.FolderId = UserInfo.getUserId(); // put it in running user's folder
try {
document.type = 'jpg';
document.IsPublic = true;
insert document;
// ImageId = '06990000001HnuB';
b = document.Body;
//ConnectApi.ChatterUsers newPhoto = new ConnectApi.ChatterUsers();
} catch (DMLException e) {
ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR, 'Error uploading file'));
return null;
} finally {
document.body = null; // clears the viewstate
document = new Document();
}
ApexPages.addMessage(new ApexPages.message(ApexPages.severity.INFO, 'File uploaded successfully : ' + b));
String communityId = null;
String userId = UserInfo.getUserId();
//ID fileId = ImageId;
// Set photo
ConnectApi.Photo photo = ConnectApi.ChatterUsers.setPhoto(communityId, userId, new ConnectApi.BinaryInput(b, 'image/jpg', 'userImage.jpg'));
return null;
}
I was getting the same error, there isn't too much detail so I'm not too sure about your problem. I solved the problem using the code below. Modify as needed.
public static Boolean updateUserProfilePic(String userProfilePicString, String userId, String fileType){
Boolean updateSuccessful = true;
System.debug('-------------' + userProfilePicString.length());
try{
Blob blobImage = EncodingUtil.base64Decode(userProfilePicString);
ConnectApi.BinaryInput fileUpload = new ConnectApi.BinaryInput(blobImage, 'image/jpg', 'userImage.jpg');
ConnectApi.Photo photoProfile = ConnectApi.UserProfiles.setPhoto(null, userId, fileUpload);
}
catch(Exception exc){
updateSuccessful = false;
}
return updateSuccessful;
}

Android: Retrofit 2 multiple file upload howto?

Uploading a single image seems to be no problem with retrofit 2.
However,
i cant figure out how to upload 2 images at the same time.
if followed the documentation:
http://square.github.io/retrofit/2.x/retrofit/retrofit2/http/PartMap.html
File file = new File(path, "theimage");
File file2 = new File(path2, "theimage");
RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);
RequestBody requestBody2 = RequestBody.create(MediaType.parse("image/png"), file2);
Map<String, RequestBody> params = new HashMap<>();
params.put("image2", requestBody2 );
Call<ResponseBody> call = service.upload(requestBody, params);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
Log.v("Upload", "success");
}
interface:
public interface FileUploadService {
#Multipart
#POST("/upload")
Call<ResponseBody> upload(
//#Part("image_logo\"; filename=\"image.png\" ") RequestBody file,
#Part("file") RequestBody file,
#PartMap Map<String, RequestBody> params
// #Part("description") String description
);
this gives a 'Upload: success' but on the server side i get gibberish:
CONTENT_TYPE: multipart/form-data;
boundary=50fbfeb3-3abc-4f15-b130-cdcb7e3a0e4f
CONTENT POST:Array (
[file] => �PNG IHDR L alotofbinarygibberish.... ... snip
[file2] => �PNG
IHDR L more binary gibberish...
can anyone point me in the right direction?
single upload does work so thats not the problem, i'm trying to upload 2 or more images.
if i change it to this:
HashMap<String, RequestBody> partMap = new HashMap<String, RequestBody>();
partMap.put("file\"; filename=\"" + file.getName(), requestBody);
partMap.put("file\"; filename=\"" + file2.getName(), requestBody);
Call<ResponseBody> call = service.upload(partMap);
#Multipart
#POST("/upload")
Call<ResponseBody> upload(
#PartMap() Map<String, RequestBody> partMap,
i get no gibberish but only the second image is uploaded... !?
UPDATE
i tried this Retrofit(2.0 beta2) Multipart file upload doesn't work solution but get an error that #body can not me used with multipart:
Java.lang.IllegalArgumentException: #Body parameters cannot be used with form or multi-part encoding. (parameter #1)
for (String key : keys) {
Bitmap bm = selectedImages.get(key);
File f = new File(saveToInternalStorage(bm, key), key);
if (f.exists()) {
buildernew.addFormDataPart(key, key + ".png", RequestBody.create(MEDIA_TYPE, f));
}
}
RequestBody requestBody = buildernew.build();
-
Call<ResponseBody> upload(
#Body RequestBody requestBody
This works:
final MediaType MEDIA_TYPE=MediaType.parse("image/png");
HashMap<String,RequestBody> map=new HashMap<>(selectedImages.size());
RequestBody file=null;
File f=null;
Set<String> keys = selectedImages.keySet();
for (String key : keys) {
try {
Bitmap bitmap = selectedImages.get(key);
f = new File(saveToInternalStorage(bitmap, key), key);
FileOutputStream fos = new FileOutputStream(f);
if(bitmap!=null){
bitmap.compress(Bitmap.CompressFormat.PNG, 0 , fos);
fos.flush();
fos.close();
}
} catch (Exception e) {
e.printStackTrace();
return;
}
file=RequestBody.create(MEDIA_TYPE, f);
map.put(""+key+"\"; filename=\""+key+".jpg",file);
Log.i("##MYLOG###", "### MAP PUT:" + key + " filename:"+key+".jpg file:" + file.toString() +" type:"+ file.contentType() );
file=null;
f = null;
}
--
Call<ResponseBody> upload(
#PartMap() Map<String,RequestBody> mapFileAndName //for sending multiple images
--
beware: while debugging this with the httpClient.interceptors() i saw only a single upload but when checking the endpoint itself to see what it actually got, it DID get the multiple uploads!
I might be late but my answer might help future visitors
I am asking user to select multiple images like this:
int PICK_IMAGE_MULTIPLE = 1;
Intent intent = new Intent();
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_MULTIPLE);
Then in onActivityResult() I am doing this:
ArrayList<String> filePaths;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_MULTIPLE) {
if (data != null) {
filePaths=new ArrayList<>();
// If data.getData() == null means multiple images selected, else single image selected.
if (data.getData() == null) {
ClipData clipData = data.getClipData();
if (clipData != null) {
for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
Uri uri = item.getUri();
filePaths.add(FileUtils.getPath(Activity.this, uri));
}
}
} else {
filePaths.add(FileUtils.getPath(Activity.this,data.getData()));
}
sendToServer();
}
}
}
You can get FileUtils class from this Github link
My sendToServer() method looks like this:
private void sendToServer() {
if(filePaths!=null) {
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
MediaType MEDIA_TYPE_IMG = MediaType.parse("image/jpeg");
MultipartBody.Builder builder=new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
RequestBody requestBody;
try {
for (int i = 0; i < filePaths.size(); i++) {
File file = new File(filePaths.get(i));
requestBody=RequestBody.create(MEDIA_TYPE_IMG,file);
builder.addFormDataPart("photo"+i,file.getName(),requestBody);
}
RequestBody finalRequestBody=builder.build();
Call<YourResponse> call=apiService.addEvent(finalRequestBody);
call.enqueue(new Callback<YourResponse>() {
#Override
public void onResponse(Call<YourResponse> call, Response<YourResponse> response) {
// process response
}
#Override
public void onFailure(Call<YourResponse> call, Throwable t) {
t.printStackTrace();
t.getCause();
}
});
}catch (Exception e){
e.printStackTrace();
}
}
}
Finally my Retrofit endpoint looks like this:
#POST("event/add")
Call<YourResponse> addEvent(#Body RequestBody body);
Note that YourResponse can be your custom model class for handling response, or you can also use raw Response class in you don't want to make your model class.
Hope this helps new visitors.
Try This
For API:
//Multiple Images
#Multipart
#POST(HttpConstants.FILEMULTIPLEUPLOAD)
Call<Result>uploadMultipleImage(#Part MultipartBody.Part files1,#Part MultipartBody.Part files2, #Query("total_images") int total, #Query("stdID") int stdID);
Client
public class RaytaServiceClass {
public RaytaServiceClass() {
}
private static Retrofit getRetroClient(){
Gson gson = new GsonBuilder()
.setLenient()
.create();
return new Retrofit.Builder()
.baseUrl(HttpConstants.baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
public static RaytaApi getApiService(){
return getRetroClient().create(RaytaApi.class);
}
}
The Call
RaytaApi service= RaytaServiceClass.getApiService();
File file1 = new File(selectedPath1);
File file2 = new File(selectedPath2);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file1);
RequestBody requestFile2 = RequestBody.create(MediaType.parse("multipart/form-data"), file2);
MultipartBody.Part body =
MultipartBody.Part.createFormData("uploaded_file", file1.getName(), requestFile);
MultipartBody.Part body2 =
MultipartBody.Part.createFormData("uploaded_file", file2.getName(), requestFile2);
Call<Result> resultCall=service.uploadMultipleImage(body,body2,2,1);
Log.v("####WWE","REquest "+resultCall.toString());
Log.v("###WWE","Retrofit Request Method = "+resultCall.request().method());
Log.v("###WWE","Retrofit Request Body = "+resultCall.request().body());
Log.v("###WWE","Retrofit Request Url = "+resultCall.request().url());
final Result[] result = {new Result()};
resultCall.enqueue(new Callback<Result>() {
#Override
public void onResponse(Call<Result> call, Response<Result> response) {
progressDialog.dismiss();
Log.v("###WWE","Respnse");
result[0] =response.body();
Log.v("###WWE","Response Result "+result[0].getResult());
if(response.isSuccessful()){
Toast.makeText(UploadMultipleImageActivity.this,"Sucess",Toast.LENGTH_SHORT).show();
Toast.makeText(UploadMultipleImageActivity.this,"Press Refresh Button",Toast.LENGTH_LONG).show();
supportFinishAfterTransition();
}
}
#Override
public void onFailure(Call<Result> call, Throwable t) {
progressDialog.dismiss();
Log.v("###WWE","Failure ");
Log.v("###WWE","MEssage "+t.getMessage());
}
});

convert the bytes in to readable string format in blackberry?

I am working on an BB app in which I need to maintain a HTTP connection and with a name of image which is stored on server to get the text written in that image document.
I am getting the response in RTF format.
When I directly hit the server on open browser Chrome, I RTF file get downloaded.
Now I needs to perform that programetically,
1) Either convert the bytes which are coming in response in a simple string format so that I can read that.
or
2) Download the file as its happening on the browser manually so that by reading that file I read the information written in the document.
please suggest me how can I read the data from server by hitting any URL?
Currently I am working with this code:
try {
byte []b = send("new_image.JPG");
String s = new String(b, "UTF-8");
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
public byte[] send(String Imagename) throws Exception
{
HttpConnection hc = null;
String imageName = "BasicExp_1345619462234.jpg";
InputStream is = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] res = null;
try
{
hc = (HttpConnection) Connector.open("http://webservice.tvdevphp.com/basisexpdemo/webservices/ocr.php?imgname="+imageName);
hc.setRequestProperty("Content-Type", "multipart/form-data;");
hc.setRequestMethod(HttpConnection.GET);
int ch;
StringBuffer sb= new StringBuffer();
is = hc.openInputStream();
while ((ch = is.read()) != -1)
{
bos.write(ch);
sb.append(ch);
}
System.out.println(sb.toString());
res = bos.toByteArray();
}
catch(Exception e){
e.printStackTrace();
}
finally
{
try
{
if(bos != null)
bos.close();
if(is != null)
is.close();
if(hc != null)
hc.close();
}
catch(Exception e2)
{
e2.printStackTrace();
}
}
return res;
}
The response is like:
{\rtf1\ansi\ansicpg1252\uc1\deflang1033\adeflang1033...................
I can read the data but its not formatted, so that i can read that programetically too.
I have done with this task....
Actually the mistake was on server side.
When they were performing OCR, the format parameter was not corrected that was reason.

HttpWebRequest not downloading all data

I'm trying to download xml files using httpwebrequest using the code below based on this example here. Now it works partially in that it doesn't download all the xml file's contents. Any idea why?
public void download(String url)
{
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.AllowReadStreamBuffering = false;
request.Method = "GET";
request.BeginGetResponse(a =>
{
StringBuilder data=null;
using (WebResponse response = request.EndGetResponse(a))
{
int expected = (int)response.ContentLength;
try
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
int read = 0;
data = new StringBuilder(expected);
char[] buffer = new char[1024];
while ((read = reader.Read(buffer, 0, buffer.Length)) != 0)
{
data.Append(new string(buffer, 0, read));
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("exception caught: " + ex.Message);
}
}
System.Diagnostics.Debug.WriteLine("Got \n " + data.ToString());
}, null);
}
If all you're getting is XML, you can use XDocument.Load(stream) to load the result to a XDocument instance
Your problem may be with the applied Encoding, and this method should solve any Encoding issue!

how to send mail with image attachment in blackberry

I am developing a BlackBerry application that uses the Mail functionality. My problem is
I want to send mail with an image attachment. How can I do that?
You can convert the image to byte array and then use the following method to send the file as attachment.
public synchronized boolean sendMail(final byte []data)
{
Folder[] folders = store.list(4);
Folder sentfolder = folders[0];
// create a new message and store it in the sent folder
msg = new Message(sentfolder);
multipart = new Multipart();
textPart = new TextBodyPart(multipart,"Image");
Address recipients[] = new Address[1];
try {
recipients[0] = new Address(address, "XYZ");
msg.addRecipients(Message.RecipientType.TO, recipients);
msg.setSubject("Image");
try {
Thread thread = new Thread("Send mail") {
public void run() {
try {
attach = new SupportedAttachmentPart(
multipart, "application/octet-stream",
"title",data);
multipart.addBodyPart(textPart);
multipart.addBodyPart(attach);
msg.setContent(multipart);
Transport.send(msg);
}
catch(SendFailedException e)
{
}
catch (final MessagingException e) {
}
catch (final Exception e) {
}
}
};
thread.start();
return true;
}
catch (final Exception e)
{
}
}catch (final Exception e) {
}
return false;
}
This may be help you check it
//create a multipart
Multipart mp = new Multipart();
//data for the content of the file
String fileData = "<html>just a simple test</html>";
String messageData = "Mail Attachment Demo";
//create the file
SupportedAttachmentPart sap = new SupportedAttachmentPart(mp,"text/html","file.html",fileData.getBytes());
TextBodyPart tbp = new TextBodyPart(mp,messageData);
//add the file to the multipart
mp.addBodyPart(tbp);
mp.addBodyPart(sap);
//create a message in the sent items folder
Folder folders[] = Session.getDefaultInstance().getStore().list(Folder.SENT);
Message message = new Message(folders[0]);
//add recipients to the message and send
try {
Address toAdd = new Address("email#company.com","my email");
Address toAdds[] = new Address[1];
toAdds[0] = toAdd;
message.addRecipients(Message.RecipientType.TO,toAdds);
message.setContent(mp);
Transport.send(message);
} catch (Exception e) {
Dialog.inform(e.toString());
}
this is for Image file
InputStream inputStream;
FileConnection fconn = (FileConnection) Connector.open(fName, Connector.READ_WRITE);
if(fconn.exists()){
inputStream=fconn.openInputStream();
byte[] data = IOUtilities.streamToBytes(inputStream);
inputStream.close();
fconn.close();
Multipart multipart = new Multipart();
SupportedAttachmentPart attach = new SupportedAttachmentPart(multipart, ".txt/.jpeg", "attachment1", data);
multipart.addBodyPart(attach);
}

Resources