MailKit - How can bodybuilder help create a complex email body with many images interspersed with text? - mailkit

For example, what if you need to create an email body like this:
Text ...
Image ...
Text ...
Image ...
Text
Here is one of the examples that works for one text and one image:
var builder = new BodyBuilder ();
var pathImage = Path.Combine (Misc.GetPathOfExecutingAssembly (), "Image.png");
var image = builder.LinkedResources.Add (pathLogoFile);
image.ContentId = MimeUtils.GenerateMessageId ();
builder.HtmlBody = string.Format (#"<p>Hey!</p><img src=""cid:{0}"">", image.ContentId);
message.Body = builder.ToMessageBody ();
Can we do something like builder.HtmlBody += to just keep adding more and more texts and images?

The BodyBuilder class is designed to constructing typically message structures, not the type of thing you are doing.
You will need to construct your message manually, not using BodyBuilder.

After quite a bit of trial/error/testing, I discovered that you can indeed keep adding text and images to the HtmlBody object, as my question speculated, by using builder.HtmlBody +=
In response to the increasingly widespread use of TLS instead of SSL, and therefore the need to abandon the use of Microsoft's obsolete SmtpClient component, I have developed a comprehensive emailing test component, in Visual Basic, using the wonderful MailKit from JStedfast.
As my question suggested, I wanted to give my users the ability to compose a handsome email body using text interspersed with images as needed. If any VB developers would like to benefit from this work, just let me know.
#jstedfast - I just saw your answer after posting this. For my production version, I need to add images from a blob field in a SQLServer table. I intend to use the manual method, as you stated, to do that. But for images I was loading into my sample program, I was able to make a fairly complex email body using src=file for each image, and adding them with builder.HtmlBody +=

Related

Use Google Scripts to Attach PDF to email

I am trying to have google Scripts send a PDF as an attachment to an email. I have a doc template that uses form data that is copied and then filled out. The code works, but the program keeps sending the template as a pdf and not the filled out copy. Can anyone help me with this?
Here is some of my code:
newDoc = autoWriteNewIEPForm(templateDocId, newDocName, fieldArray, NewEntryArray, submitTeacherName);
newDocId = newDoc.getId();
newDocURL = newDoc.getUrl();
var sender = newEntryArray[0][3];
var subSubject = newDocName;
var subEmailBody = "Thank you for submitting this information. This receipt confirms that we have received your information." + "<br><br>";
var file = DriveApp.getFileById(newDocId).getAs(MimeType.PDF);
MailApp.sendEmail(sender, subSubject, "", {cc:emailCC, htmlBody:subEmailBody, attachments:[file], name: newDocName});
Well the last line of your code is correctly attaching the newDoc as an attachment. The first line confuses me a bit; autoWriteNewIEPForm is not a Google scripts function, and I don't know where you're getting it from or if you're using it correctly. My guess is that you're using it incorrectly, or that for some reason it's not editing any of the text in the newDoc, so you have a document that is technically a copy of the template but looks exactly the same.
In the Body class of the Google Scripts DocumentApp you can find a number of methods for editing text in a document's body. I suggest you use one of those instead.

Xpages PDF creation using the XMLWorker class

Using SSJS I've successfully created a PDF using the simple HTML parser that comes with iText but the simple HTML parser doesn't respect CSS and is very limited. I downloaded the XMLWorker class from the iText site and have tried to use that instead but my knowledge of working out how to call Java packages is too limited. All the examples I can find use Java and refer to the classes directly, eg.
Document newPDF = new Document();
But in SSJS we have to use dot notation, eg.
var newPDF:com.itextpdf.text.Document = new com.itextpdf.text.Document();
This - I think - is where I stumble. My code looks like this:
function createLPO2(pReqDoc:NotesDocument) {
importPackage(com.itextpdf);
//importPackage(com.itextpdf.tool.xml.XMLWorkerHelper);
importPackage(java.io);
var con = facesContext.getExternalContext();
var response:com.ibm.xsp.webapp.XspHttpServletResponse = con.getResponse();
response.setContentType("application/pdf");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", -1);
response.setHeader("Content-Disposition","attachment; filename=\"LPO_" + pReqDoc.getItemValueString("RequisitionNo") + ".pdf\"");
var newPDF:com.itextpdf.text.Document = new com.itextpdf.text.Document();
var writer = com.itextpdf.text.pdf.PdfWriter.getInstance(newPDF,response.getOutputStream());
var xmlWorkerHelper = com.itextpdf.tool.xml.XMLWorkerHelper.getInstance();
var strHTML = getTestHTML(); //this is the HTML used in the examples on the iText site
xmlWorkerHelper.parseXHtml(writer, newPDF, new java.io.StringReader(strHTML));
newPDF.close();
writer.close();
facesContext.responseComplete();
}
If I run this script as it is I get a script error on the Domino console. If I remove the comment on the line importPackage(com.itextpdf.tool.xml.XMLWorkerHelper); it gives a completely different error. I suspect I have to import the XMLWorkerHelper package and not just the com.itextpdf package. I thought if I opened the jar file using a tool like 7-zip I could work out the path, which is how I arrived at com.itextpdf.tool.xml.XMLWorkerHelper
Is this right? If so, why does my script fail?
Rob,
seriously, don't try to do that in SSJS. iText is all Java, if you try to mangle with it in a different language it will stress you out. Create a wrapper class that has a method that takes an OutputStream and whatever data (Document, View etc) you need. Obtain the OutputStream in your SSJS and call the function. Look for the XAgent XSnippet on OpenNTF and my blog series (the last two are missing - bear with me) on PDF creation.
One word of caution: iText is GPL, so you either GPL your software too, buy a commercial iText license or look for alternatives like Apache PDFBox or Apache FOP. Ah the second caution: HTML to PDF is a Pita. You could look at a commercial tool like e.g. from Swing software (or change your approach)

RMagick & Sinatra: send picture to view without storing

Currently I am writing a Sinatra app that gets some pictures from user and returns a new picture.
There's part of haml form:
%input{type:'file', name:'user_image'}
And there's a code from handler: (montage is another picture)
source_userpic = params[:user_image][:tempfile]
blob = File.open(source_userpic).read
userpic = ImageList.new
userpic.from_blob(blob)
resized_img = userpic.scale(montage.columns,
montage.rows)
resized_img.opacity = MaxRGB/3
Then two images are "layered" with composite and stored (don't need)
final_picture = ImageList.new
final_picture << montage.composite(resized_img, 0, 0, OverCompositeOp)
final_picture.write("./public/uploads/#{DateTime.now}.jpg" # dirty (for example)
Next, I need to show a final_picture with ajax. There are two obvious problems: first, I don't need to save a final_picture - it's just preview, second, I must write code to avoid filenames conflicts...
How to send a final_picture to view? to_blob method? But what's next?
I solved that by using the data URI scheme.
require 'base64'
final_picture.format = "jpeg" # whatever
# Using a to_blob method to create a direct-to-memory version of the image.
# Then encode it to base64 string
data_uri = Base64.encode64(final_picture.to_blob).gsub(/\n/, "")
#image_tag = '<img alt="preview" src="data:image/jpeg;base64,%s">' % data_uri
haml:'pages/preview'
Then display a picture by
= #image_tag
Not sure if it's best solution
Take a look at Tempfile, that should take care of file name conflicts for you.
Then you could use the technique from the answers to this question, using send_file to send the tempfile.
You have to remember that the tempfile won't persist, so you have to be careful to manage that persistence if you are using different requests and responses to serve the file.

Prevent Gmail from creating links for URLs and email addresses

Problem is Gmail automatically creates hyperlinks for all website URLs and email addresses. I do not want to create a link.
var mailClient = new SmtpClient();
var netMail = new MailMessage();
msg = "I do not want www.google.com as a link at recipient end. <br/>";
msg += "I want my email addrress myemail#myudomain.com as html without a link";
var cr = new NetworkCredential("########", "###########");
netMail.From = new MailAddress("#########m####.###", "######");
netMail.To.Add(new MailAddress("abc#xyz.com"));
netMail.Subject = "Test Mail";
netMail.IsBodyHtml = true;
netMail.Body = msg;
mailClient.Host = "xyz.com";
mailClient.Port = 25;
mailClient.EnableSsl = false;
mailClient.Credentials = cr;
mailClient.Send(netMail);
Any solution?
I had a same issue and found out if you use email like this;
<a rel="nofollow" style='text-decoration:none; color:#333'>test#mydomain.com</a>
email providers does not tend to follow email as a link.
Hope this helps.
There's no way to stop creating URLs, because its automatically checked by the email provider that whether the text is a valid URL.
Only way to overcome this is, deceiving the parser. Just put spaces, HTML tags, whatever in such a way that the parser can't identify like URL etc.
Here are a few code examples:
http:<span>//foolishedsiteparser.com</span>
_http://www.parsersmashed.com
noonesemail<x>#</x>linkdead.com>
And the result is the following:
http://foolishedsiteparser.com
_http://www.parsersmashed.com
noonesemail#linkdead.com
I was able to get around this issue just by adding <a style="color: #000000">link text</a> (notice there is no href).
I haven't tried using attributes besides style but I would imagine you could. The email system that I use (Blackbaud NetCommunity) will strip out a plain <a> tag, so I had to have at least one attribute.
Taking a cue from perilbrain's answer, I implemented the following regex that I use for this:
var unlink = function (val) {
return val.replace(/([#\.:])/g, '<span>$1</span>');
};
Note that this function replaces globally on whatever is passed in -- it would probably be too aggressive for blocks of natural text as in the OP's example, but often templates are parameterized and this works great when you can just pass it a url or email (I actually implemented it as a template helper function so that it does exactly that).
The function converts the following inputs:
john.doe#gmail.com
http://johndoe.com
into this:
john<span>.</span>doe<span>#</span>gmail<span>.</span>com
http<span>:</span>//johndoe<span>.</span>com
Note that I tried a fake short tag like <x> as shown in the accepted answer and found that GMail "intelligently" replaced it with <u> tags, which I assume is a feature, but was not desirable. In my testing, <span> tags prevent linking with no visual side-effects.
None of the solutions listed here seem to work any more. I experimented a little with the idea of non-printable Unicode characters and found this sequence to work:
<span>foo‌.‌bar‌.‌com</span>
Where ‌ is the ZERO WIDTH NON-JOINER character.
Nailed it!
This does not prevent emails from being turned into links, but it allows you to set the font color and remove the underline of that link.
It works in all email clients I tested in on litmus.com - including Outlook 2010, 2013, 2016 (also on Windows), Outlook.com, iPhone 6s, iPad, gmail web interface and Apple Mail 8, 9
Variation 1:
A link which does not react when clicked upon
bjorn#rosell.dk
Variation 2:
A mailto-link. Works in almost all clients. Outlook.com does however style it blue and with underline.
bjorn#rosell.dk
I have one unmentioned solution for textual emails: Use similar unicode characters. For example one dot leader (U+2024) instead of dot. Compare, how looks Běhej.com and Běhej․com (the first one is with regular dot).
I had a dot com in the title of my confirmation message.
Inspired by #perilbrain, I revolved my problem like this
domain.com => domain<span>.</span>
php
$titre = str_replace(".", "<span>.</span>", $titre);
simple !
For now simple wrapping by <span> is not working, I suggest replace # by its html-entity alternative
function disable_email_link($email) {
//encoder https://mothereff.in/html-entities
$email = str_replace('#', '#', $email);
$email = str_replace('.', '<span>.</span>', $email);
return $email;
}
Also if your email contains phone numbers you can escape it by disable_tel_link function:
function wrap_span_letters($string) {
$res = "";
$length = strlen($string);
for ($i = 0; $i < $length; $i++) {
$res .= "<span>$string[$i]</span>";
}
return $res;
}
function disable_tel_link($phone) {
return wrap_span_letters($phone);
}
Eventhough this is a old thread i want to help people who might get here. I found that adding a span inside the link makes google not see it as a link see below:
www.<span></span>link.dk
i had the same problem so after few mins found out how to fix it.
the thing is if you target the element directly it won't work because gmail will automatically add aa "a" tag in there so you have to go one step farther and declare a class for that "a" tag. in my case the email was in a "" tag which i found it easier to work with. so what i did was create a class like this:
.email_contact a {color:#ffffff!important; text-decoration: none!important;}
there is no "a" tag in my code but since gmail will add it automatically then you should catch it there. now you just have to use that class where ever you put your email add such as "span" or "div" and boom! fixed.
While not the ideal solution, it may be an option for some. As of 3/12/2020, If you disable Multipart and send plain text only emails, you'll get the following hyperlinked results. Results appear to be the same whether at the beginning of a new line/sentence or mid sentence.
Suppose your display url is "abcdUrl.com"
To prevent gmail from showing as a link, wrap it in an anchor tag
<a href="" style="text-decoration:none;color:#333;">
abcdUrl.com
</a>
This works well in gmail.

How to access hyperlinks in PDF documents (iPhone)?

Is it possible to get access to "internal" links in PDF documents using CGPDFDocument, or other means? I'm building a simple reader app and would like to deliver my content in PDF form, but if I can't support links between pages in the doc this probably isn't going to work.
This question is similar, but does not address the issue of how to support hyperlinks.
See my answer here. Basically, you'll need to get familiar with PDF link annotations.
see this sample code...pdf hyperlinks works in this
https://github.com/vfr/Reader
If you're using Quartz to open and view a PDF, then yes, it looks like you will have access to internal links. Quartz will also let you add new links to PDFs. I don't have any first hand experience with iPhone/Mac development, but it would be quite strange for them to let you add hyperlinks, but not use them.
You need to do in two steps.
First: Parse your pdf to locate marked content operators
That's an exemple of a parsing code :
-(void)parseContent() {
CGPDFOperatorTableRef myTable;
myTable = CGPDFOperatorTableCreate();
CGPDFOperatorTableSetCallback(myTable, "BMC", &myOperator_BMC);
CGPDFContentStreamRef myContentStream = CGPDFContentStreamCreateWithPage(page);
CGPDFScannerRef myScanner = CGPDFScannerCreate(myContentStream, myTable, autoZoomAreas);
CGPDFScannerScan(myScanner);
CGPDFScannerRelease(myScanner);
CGPDFContentStreamRelease(myContentStream);
}
void myOperator_BMC(CGPDFScannerRef s, void *info)
{
const char *name;
CGPDFScannerPopName(s, &name);
}
(You need to complete and adjust this code to match your requirement)
Second: respond to the toucheEnded message to handle tap on those zones and make the UI respond accordingly.