AWS Lambda: How to extract attachment (xls) from raw email? - email

I have raw emails in an S3 bucket. I'm writing an AWS Lambda function to extract the .xls attachment and save it to another S3 bucket. So far I have Lambda read the raw body of the email, but how do I extract the attachment?
s3.getObject({
Bucket: bucketName,
Key: sesNotification.mail.messageId
}, function(err, data) {
if (err) {
console.log(err, err.stack);
context.fail();
} else {
console.log("Raw email:\n" + data.Body);
// Extract xls and copy to bucket
context.succeed();
}
});
Attachment in email body:
------=_Part_3703880_1038025051.1459895117742
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=Book1.xlsx
Content-ID: <223412a-63b2-9471-19a8-f94640ef04a5#yahoo.com>
UEsDBBQABgAIAAAAIQDIo800dgEAAAQFAAATAN0BW0NvbnRlbnRfVHlwZXNdLnhtbCCi2QEooAAC
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

the attachment is also in raw data so you need a way to "transfer" or decode that into the actual file contents that you can process.
Take a look at the python core library "email" for more details.

Related

Mailparser ignores attachments' headers

I'm sending an email with attachments, which look like
const attachment = { filename, path, size, headers: { uid: 'someId' } };
According to the Nodemailer's docs I can set attachment's headers in the same format as message headers.
At the receiver's side the email is parsed by simpleParser (from mailparser). Parsed email looks great, it has all attachment's info but the headers are empty {}. But the raw email source has the following:
----_NmP-30615c8ac620489d-Part_1
Content-Type: image/jpeg; name=attachment.jpg
Uid: someId
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=attachment.jpg
The uid header is there, but it is lost after parsing.
Also tried headers in the following format: headers: [{ header: 'uid', value: 'someId' }]. But it doesn't help.
How can I get that headers correctly? Or this can be the mailparser's bug?
After few hours of mailparser's source code researching I discovered that mailparser returns headers as Map, that's why it looks like Object {} which seems to be empty, but it's not.

How to force Google Storage file to have `content-disposition: inline` instead of `attachment`?

I'm using GoogleApi.Storage.V1.Api.Objects.storage_objects_insert_simple to upload files to Google Storage. However, it seems that no matter what I do, the content-disposition HTTP response header is being set to attachment which forces browsers to download a file rather than displaying it in a browser tab.
Here's my usage:
{:ok, object} =
GoogleApi.Storage.V1.Api.Objects.storage_objects_insert_simple(
gconn,
"my-uploads-bucket",
"multipart",
%{
name: Path.basename(path),
contentType: content_type,
contentDisposition: "inline" # <-- this doesn't seem to have an effect
},
path
)
Does anyone know how to force the content disposition header to have a value of inline?
Update
After inspecting the value of object, I'm seeing the following:
%GoogleApi.Storage.V1.Model.Object{
acl: nil,
bucket: "my-uploads-bucket",
cacheControl: nil,
componentCount: nil,
contentDisposition: "inline", # <-- !!!
contentEncoding: nil,
contentLanguage: nil,
contentType: "image/png",
crc32c: "MGa01Q==",
...
However, after fetching a file via curl -I <url>, I see the following:
HTTP/2 200
...
content-type: image/png
content-disposition: attachment
...
It seems like my mistake here was in using the mediaLink field as the URL. This URL even has download as part of the URL: https://storage.googleapis.com/download/storage/....
If I instead use name field to build the URL, then it works as expected.
send_resp(
conn,
200,
"https://storage.googleapis.com/my-bucket/" <> object.name
)

File not uploading in server ionic3

I have a scenario where I am uploading a image file from my local drive (type jpeg or png) to an API endpoint using ionic. Here is my code below :
fileupload.html -->
//---------------------------------------------------
<ion-item>
<ion-input type="file" accept="image/*" (change)="changeListener($event)"> </ion-input>
</ion-item>
fileupload.ts -->
changeListener($event):void{
this.file=$event.target.files[0];
console.log(this.file);
console.log("upload...");
let regData={"file":this.file};
console.log("REGDATAA"+JSON.stringify(regData));
this.jira.postAttachment("PM-3",regData).subscribe(dataa=>{
console.log(dataa);
});
}
provider.ts -->
public postAttachment(key,data):Observable<any>{
console.log(JSON.stringify(data))
return this.http.post(this.api+'/issue/'+key+'/attachments',JSON.stringify(data),{
headers: new HttpHeaders()
.append('Authorization', `Basic ${this.auth.getAuthString()}`)
.append('Content-Type','multipart/form-data';boundary="-------xe3rtyhrfds")
.append("X-Atlassian-Token", "no-check")
.append("User-Agent", "xx")
});
}
every time I send the file it doesn't take the path and sends an empty response, here is the error below.
//----------------------------------------------------
[object File]: {lastModifiedDate: [date] Fri Sep 21 2018 17:42:46 GMT+0530 (India Standard Time), name: "download.jpg", size: 5056, type: "image/jpeg", webkitRelativePath: ""}
upload...
ion-dev.js (157,11)
REGDATAA{"file":{}}
ion-dev.js (157,11)
{"file":{}}
ion-dev.js (157,11)
ERROR [object Object]
I have resolved CORS issue and there is no problem with the same.
When I send the same response using postman it succeeds here is what I send in Postman.
Form-data
key - "file" (type file) value - "/path/to/my/file"
Headers
Content-type - application/json
x-attlassian token - no-check
Can somebody advice what is going wrong here.
Use FormData to upload file.
fileupload.ts
changeListener(event) {
const fd = new FormData();
this.file = event.target.files[0];
fd.append('file', this.file, this.file.name);
this.jira.postAttachment("PM-3",fd)
.subscribe(data => {
console.log(data);
});
}
provider.ts
postAttachment(key, fd): Observable<any> {
const httpOptions = {
headers: new HttpHeaders(
{ 'Content-Type': 'multipart/form-data' },
{ 'Authorization': `Basic ${this.auth.getAuthString()}` })
};
return this.http.post(this.api+'/issue/'+key+'/attachments', fd, httpOptions);
}
Your have to change the content type from application/json to multipart/form-data. You are sending an image, not a json-file.
Best way is to encode your image to base64 and send it. Everything depends about what your server needs.
or you can try this.
const body = file;
const headers = new Headers({'Content-Type': 'image/jpg'});
return this.http.post(this.api+'/issue/'+key+'/attachments, body, {headers: headers}). ...
For an issue on AngularJS what ended up working is (might a similar aproach help you too) :
make a hidden input de type file
set it's value in the changeListener function
make the file send from there afterwards
The reason being some built in propertie of the file input let's its value be recognised as File/Blob instead of the path many "complex" components use.
Also send it as multipart file as mentioned before.

How to send pdf file as an attachment in sendgrid node.js v3 client

I am using v3 node.js client to send an email. Now , I want to send pdf attachment with the email. I went through the API documentation. But I did not find anywhere how to do it.
I am using the following code to send an email.
const msg = {
to: process.env.EMAIL_ID,
from: process.env.ALERT_EMAIL_ID,
subject: subjectText,
text: info
};
sgMail.send(msg);
Let us assume your PDF is in S3.
Get your file from S3
const pdfFile = await s3
.getObject({
Bucket: PDF_BUCKET_NAME,
Key: `flight-${fileName}.pdf`,
})
.promise();
Once you have the file
const base64data = pdfFile.Body.toString('base64');
const data = {
from: 'text#example.in',
to: user.emailId,
subject: 'Your ticket for flight PNR XYSSA1 from DEL-BLR',
html: `Please find attached your ticket
<br><br>Regards<br>
Team Example`,
attachments: [
{ content: base64data, filename: 'flight-ticket', type: 'application/pdf', disposition: 'attachment' },
],
};
await sgMail.send(data);
In case you have your file in the filesystem, just get the buffer from fs.readFile convert it into base64 like shown above and repeat the steps and you should be good to go.

Send mail with attachment using mailjet in GAS

I am trying to send mail with a PDF attachment using Mailjet from Google Apps Script. I can send regular mail without issue, but not quite sure how to include an attachment.
Mailjet documentation: https://dev.mailjet.com/guides/#sending-with-attached-files
I think my problem is the Base64Content. I don't really understand how to encode the attachment. When I execute the below code, an email is being sent with a PDF attachment, but when I try and open the PDF it displays: "Cannot display PDF (test.pdf is of invalid format)".
var newDoc = DocumentApp.openById(newDocid)
var attachment = newDoc.getAs(MimeType.PDF);
var mailjeturl = "https://api.mailjet.com/v3.1/send";
var mailjetparams = {
"Messages":[{
"From": {"Email": 'myemail#domain.com',"Name": 'Robert'},
"To": [{"Email": 'theiremail#domain.com'}],
"Subject": 'subject',
"HTMLPart": 'this message',
"Attachments": [{"ContentType": "application/pdf",
"Filename": "test.pdf",
"Base64Content": Utilities.base64Encode(attachment)}]
}]
}
var mailjetoptions = {
'method': 'post',
'contentType': 'application/json',
'payload': JSON.stringify(mailjetparams),
'headers': {'Authorization': 'Basic ' + Utilities.base64Encode(MAILJET_KEY)}
};
var response = JSON.parse(UrlFetchApp.fetch(mailjeturl, mailjetoptions))
Try to encode like this:
var pdf = newDoc.getAs('application/pdf').getBytes();
var attach = {fileName:'test.pdf',content:pdf, mimeType:'application/pdf'};
var mailjetparams = {
"Messages":[{
"From": {"Email": 'sender#domain.com',"Name": 'Robert'},
"To": [{"Email": 'reciever#domain.com'}],
"Subject": 'subject',
"HTMLPart": 'this message',
"Attachments": [attach]
}]
}
How about the following modification? I thought that the reason of the error may be Utilities.base64Encode(attachment).
Modification points :
attachment retrieved by newDoc.getAs(MimeType.PDF) is Blob. The Blob cannot be directly converted to base64 using Utilities.base64Encode(). So please convert Blob to byte array, and convert to base64.
When this is reflected to your script. The modification part is as follows.
From :
var attachment = newDoc.getAs(MimeType.PDF);
To :
var attachment = newDoc.getAs(MimeType.PDF).getBytes();
or
var attachment = newDoc.getBlob().getBytes();
When Google Document is retrieved as a Blob, Google converts automatically to PDF. You can also use this.
Reference :
base64Encode()
If I misunderstand your question, I'm sorry.