Reputation: 5291
I am using grails Async Mail plugin to send emails with attachments in my app. to achieve that I have written following code
def sendEmail = {
def documentsInstances = Documents.getAll(params.list('ids[]'))
def s3Service = new AmazonS3Service()
documentsInstances.each(){documentsInstance->
asyncMailService.sendMail {
multipart true
to documentsInstance.author.emailAddress
subject 'Test';
html '<body><u>Test</u></body>';
attachBytes documentsInstance.filename , 'text/plain', s3Service.getBytes(session.uid,documentsInstance.filename);
}
}//
}
Now the code above works pretty much correctly but it sends an email per attachment, I am not sure how can I move this loop inside send mail so that I can send multiple attachments in an email.
Also is there a way to send an email so that I don't have to load a whole file in byte[]?
I am using JetS3t for access to Amazon S3 and I tried "attach" method with
new InputStreamResource(s3Obj.getDataInputStream())
ie
attach documentsInstance.filename , 'text/plain', new InputStreamResource(s3Obj.getDataInputStream());
but I am getting
"Passed-in Resource contains an open stream: invalid argument. JavaMail requires an InputStreamSource that creates a fresh stream for every call"
Upvotes: 3
Views: 3448
Reputation: 39570
You need your loop inside the email:
def sendEmail = {
def documentsInstances = Documents.getAll(params.list('ids[]'))
def s3Service = new AmazonS3Service()
asyncMailService.sendMail {
multipart true
to documentsInstance.author.emailAddress
subject 'Test';
html '<body><u>Test</u></body>';
// loop over attachments
documentsInstances.each{ documentsInstance->
attachBytes documentsInstance.filename , 'text/plain', s3Service.getBytes(session.uid, documentsInstance.filename);
}
}
}
This should attach multiple files.
If it throws an error about not being able to find an attachBytes
method, you might need to explicitly call owner.attachBytes
instead, which should refer to the outer sendMail
closure.
Update based on comments:
The Async plugin looks like it defers to the normal mail plugin. The normal mail plugin's docs describes how to use multiple attachments.
This would look something like:
// loop over attachments
documentsInstances.each{ documentsInstance->
attach documentsInstance.filename , 'text/plain', s3Service.getBytes(session.uid, documentsInstance.filename);
//^^^^^^ Notice, just 'attach', not 'attachBytes'
}
I don't know the S3 plugin you are using, but if there is a way to retrieve an InputStreamSource
from it, it appears that you can stream the bytes directly to the mail plugin, instead of loading them into memory.
Upvotes: 3