HTML content is not rendered in an Email [duplicate] - javascript

This question already has answers here:
mailto link with HTML body
(10 answers)
Closed 7 years ago.
I want to open (not send) an email with a content in HTML format.
I'm using mailto of javascript, and I have created a string that contains the html in c#.net, but the mail shows the tags instead of rendering HTML. I guess I am missing a content-type: text/html but how do I put it? or is there a more correct way to do open email with content ?
Here's the c#.net code that gets the html page
[HttpPost]
public ActionResult SetMailContent(int entreatyID)
{
Entreaties entreaty = db.Entreaties.Where(e => e.ID == entreatyID).FirstOrDefault();
if (entreaty == null)
{
return new HttpStatusCodeResult(HttpStatusCode.NotFound, "File Not Found");
}
StringWriter stringWriter = new StringWriter();
using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter))
{
writer.RenderBeginTag(HtmlTextWriterTag.H1);
writer.Write(entreaty.OpenDate.ToString("dd/MM/yyyy"));
writer.RenderEndTag();
}
string msg = stringWriter.ToString();
return Json(new { message = msg});
}
and javascript code:
window.location = "mailto:mail#gmail.com?body=" + SetMailContent(EntreatyID) + "&subject= " + EntreatyID;
Thank you for your help.

You need to add the HTML content to the DOM, not just display it as a string. You can do this via jQuery for example:
$("#containerId").append($("your mail content"));

Related

Questions about how to move url in JavaScript [duplicate]

This question already has answers here:
How do I parse a URL into hostname and path in javascript?
(26 answers)
Adding a parameter to the URL with JavaScript
(36 answers)
Closed 3 months ago.
I'm using this button in HTML. Below is a description of the button, followed by a description of "functionclick().
<button type="submit" class="btn btn-primary" ONCLICK="functionclick()">확인</button>
<script type="text/javascript">
function functionclick() {
let id = document.getElementById('exampleDropdownFormEmail1').value;
let password = document.getElementById('exampleDropdownFormPassword1').value;
if (id == "" || password == "") {
alert("회원 정보를 입력하세요");
history.back();
} else{
var path= "/tryLogin?id=" + id + "&password=" + password;
const url = new URL(path);
window.location.href = url;
}
}
</script>
Uncaught TypeError: Failed to construct 'URL': Invalid URL
at functionclick (login:23:23)
at HTMLButtonElement.onclick (login:83:81)
functionclick # login:23
onclick # login:83
I don't know much about JavaScript grammar. So I have a lot of difficulties in doing simple things... I need your help.
The result I expected is to send a 'GET' request to the server while moving the page to url in "var path".
But It doesn't worked and popped up this error where the chrome debugger

Line chart generated image that will be sent through email

I want to create a line chart similar below:
I just wonder if there are available framework or API available in ASP.NET MVC that generates chart images since my goal is to send this via email. I'm thinking if I can just put something like <img src="http://imageapi.com?date1=20170101&date=20170130" /> then api will be handling the chart image generation.
On searching, I found a lot of chart framework using javascript but I doubt it will properly work on different email clients.
Thanks a lot!
Google Image Charts will do that. Pass data and display settings via the URL, and it will return an image.
eg.
<img src="https://chart.googleapis.com/chart?cht=lc&chd=t:30,10,45,38,25|10,20,10,20,10&chls=2.0,0.0,0.0&chs=200x125&chg=0,20,3,3,10,20&chxt=x,y&chxl=0:|Week1|Week2|Week3|Week4|Week5|1:|0|20|40|60|80|100&chs=800x300&chm=o,ff9900,0,-1,10.0|d,ff0000,1,-1,10.0&chco=FFC6A5,DEBDDE&chdl=Click|GRU" />
produces this chart:
They provide a playground for testing: https://developers.google.com/chart/image/docs/chart_playground
Note however that Google are not maintaining it further, but have no plans to remove this functionality:
While the dynamic and interactive Google Charts are actively maintained, we officially deprecated the static Google Image Charts way back in 2012. This gives us the right to turn it off without notice, although we have no plans to do so.
What is your design ?
Your chart must be generated in web page,then it must be having html generated.
If no html is generated and only image is generated then this is best.
now you can send same content in.
If image is not generated then again you have 2 option here
i) Send complete html in email body along with concern js/css
ii) you can convert those html into image using(say c#) then send mail.
Please mention your complete scenario.
There are different types of chart API available in market, both open source and licensed, you can use any one to generate your chart/diagram in page and you can send that page as an email attachment using following code.
[HttpPost]
public ActionResult SendWebPageAsAttachment()
{
var subject = Request.Form["subject"]; // You can provide subject from page or code
var mailContent = Request.Form["bodyInnerHTML"]; // get the body inner HTML by form name
var Body = "<div style='background-color:white;'>" + Request.Form["mailContent"] + "</div>"; // Email Body
var attachmentName = DateTime.Now.ToString("yyyy/MM/dd").Replace("/", "-") + "_" +
DateTime.Now.ToLongTimeString().Replace(" ", "_") + ".html"; // Attachment Name
var baseUrl = HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority +
HttpContext.Request.ApplicationPath.TrimEnd('/') + '/'; // Base URL
string src = #"src=""";
mailContent = mailContent.Replace(src, src + baseUrl.Remove(baseUrl.Length - 1));
mailContent = "<html><head><link href='" + baseUrl + "Themes/styles.css' rel='stylesheet' type='text/css' /><link href='" +
baseUrl + "Themes/style.css' rel='stylesheet' type='text/css' /></head><body>" + WebUtility.HtmlDecode(mailContent) +
"</body></html>";
try
{
SmtpClient smtpClient = new SmtpClient("mail.MyWebsiteDomainName.com", 25);
smtpClient.Credentials = new System.Net.NetworkCredential("info#MyWebsiteDomainName.com", "myIDPassword");
smtpClient.UseDefaultCredentials = true;
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
smtpClient.EnableSsl = true;
MailMessage mail = new MailMessage();
//Setting From , To and CC
mail.From = new MailAddress("info#MyWebsiteDomainName", "MyWeb Site");
mail.To.Add(new MailAddress("info#MyWebsiteDomainName"));
mail.CC.Add(new MailAddress("MyEmailID#gmail.com"));
mail.IsBodyHtml = true;
mail.Subject = subject;
mail.Body = Body;
var mailDataBytes = ASCIIEncoding.Default.GetBytes(mailContent);
var mailStream = new MemoryStream(mailDataBytes);
mail.Attachments.Add(new Attachment(mailStream, attachmentName));
smtpClient.Send(mail);
}
catch (Exception ex)
{
//catch
}
ViewBag.IsHttpPost = true;
return View("SendWebPageAsAttachment");
}

Embed image in mail Body using mailto function [duplicate]

This question already has answers here:
mailto link with HTML body
(10 answers)
Closed 6 years ago.
I am using mailto function my requirement is like to embed image inside mail body
$scope.generateMail = function () {
var graph = document.getElementById('thumb_graphs_grp');
html2canvas(graph).then(function(canvas) {
var dataURL = canvas.toDataURL();
var image = new Image();
image.src = canvas.toDataURL("image/png");
var imageHTML = "<img " + "src='" + image.src + "' img/>";
var link = "mailto:mail#example.org?subject=Mail request&body="+ imageHTML;
window.location.href = link;
});
As stated in the RFC2368, it's not possible to include HTML with mailto:
The special hname "body" indicates that the associated hvalue is the
body of the message. The "body" hname should contain the content for
the first text/plain body part of the message. The mailto URL is
primarily intended for generation of short text messages that are
actually the content of automatic processing (such as "subscribe"
messages for mailing lists), not general MIME bodies.

Servlet-Response containing text (for display) as well as file download

I'm trying to download a file from my server through a Java Servlet.
The Problem I have is that when I enter the servlet url directly (https://localhost:8443/SSP/settings?type=db_backup) I get the servlet to execute its code and prompt me with a download dialog.
But I would like to call the servlets doGet method via Javascript to wrap it with a progress bar of some kind.
Problem here: Code in servlet is executed but I dont get the download prompt for the file.
My Code so far:
HTML:
<!-- Solution #1 -->
<button class="btn_do_db_backup" type="button">DB-Backup #1</button>
<!-- Solution #2 -->
<form action="/SSP/settings?type=db_backup" method="GET">
<button type="submit">DB-Backup #2</button></br>
</form>
JS:
// Solution #1
$(".btn_do_db_backup").click(function(e){
e.preventDefault();
$.get("settings?type=db_backup", function(data){
if(data != ""){
//further coding
}
});
// Having the code below works but doesnt
// give me the chance to wrap the call with a loading animation
//document.location = "/SSP/settings?type=db_backup";
});
Servlet:
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
// PART 1
// execute srcipt to generate file to download later on
StringBuffer output = new StringBuffer();
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "D:\\TEMP\\sql_dump.cmd");
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
String filename = "";
int tmp = 0;
while (true) {
line = r.readLine();
if (line == null) { break; }
output.append(line + "\n");
// code for finding filename not optimal but works for now -> redo later on
if(tmp == 1){
filename = line.substring(line.indexOf("db_backup_"), line.indexOf('"', line.indexOf("db_backup_")) );
}
tmp++;
}
// PART 2
// download the file generated above
OutputStream out = response.getOutputStream();
String filepath = "D:\\TEMP\\sql_dump\\";
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
FileInputStream fileInputStream = new FileInputStream(filepath + filename);
int i;
while ((i = fileInputStream.read()) != -1) {
out.write(i);
}
out.close();
fileInputStream.close();
}
Solution #2 works great, I get a popup to download the file.
Solution #1 calls the servlets doGet-method (via the above JS-Code and the code from my servlet is executed correctly) but I dont get a download popup
I would like to go with solution #1 though as this gives me the opportunity to wrap the $.post call with a loading animation.
What am I missing within solution #1 to get that download popup to shop up?
EDIT 1:
I found that data in the $.get() function is filled with the content of the desired file. I can now display the content of a .txt file in a div for example but I would like to donwload said .txt file instead.
EDIT 2:
Solved it, see my answer below for details & comment/ansewer if you think it can be done in a better way
after quite some time trying to get it to work I found a solution that works. There may be better ones but thats the one I came up with.
Hope this may be helpfull for others as well.
Basic explanation of what I did here:
Have a form do a GET-Request (via JS) to a java servlet
The servlet executes a commandline script (in my case a sql-dump of my postgreSQL DB)
The servlets gathers the output from the commandline and the contents of the generated file (the sql_dump) and puts them in the response
The client gets the response and cuts it into 3 pieces (commandline output, filename & contents of sql_dump-file)
Then (via JS) the commandline output is shown in a textarea for a better overview of what the script actually did
The contents of the sql_dump-file is processed by JS-Code to generate a file to download (eihter manually via a button or automatically)
So without further ado, here we go with the flow ... code :)
SOLUTION:
HTML:
<form id="form_download_db_backup">
<input type="submit" value="Create & Download DB-Backup"></br>
<a download="" id="downloadlink" style="display: none">download</a>
</form>
<div class="db_backup_result" id="db_backup_result" style="display: none;">
</br>Commandline-Output</br>
<textarea id ="txta_db_backup_result" rows="4" cols="50"></textarea>
</div>
JS:
$("#form_download_db_backup").submit(function(e){
e.preventDefault();
var spinner = new Spinner().spin();
var target = document.getElementById('content');
target.appendChild(spinner.el);
$.ajax({
url:'settings?type=db_backup',
type:'get',
success:function(data){
spinner.stop();
if(data != ""){
var str_data = "" + data;
// Cut commanline output from data
var commandline_output = str_data.substring( 0, str_data.indexOf("--End") );
//show commanline output in textarea
$("#txta_db_backup_result").html(commandline_output);
// Cut content of db_backup file from data
var sql_dump_content = str_data.substring( str_data.indexOf("--sql_d_s--") + 13,str_data.indexOf("--sql_d_e--") );//|
// Cut filename from data
var filename = str_data.substring( str_data.indexOf("--sql_d_fns--") + 15,str_data.indexOf("--sql_d_fne--") - 2 );
//-------------------------------------------------------------
// Prepare download of backupfile
var link = document.getElementById('downloadlink');
var textFile = null;
var blob_data = new Blob([sql_dump_content], {type: 'text/plain'});
// FOR IE10+ Compatibility
if(window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob_data, filename);
}
// If we are replacing a previously generated file we need to
// manually revoke the object URL to avoid memory leaks.
if (textFile !== null) {
window.URL.revokeObjectURL(textFile);
}
textFile = window.URL.createObjectURL(blob_data);
link.href = textFile;
link.download = filename;
//link.style.display = 'block'; // Use this to make download link visible for manual download
link.click(); // Use this to start download automalically
//-------------------------------------------------------------
// show div containing commandline output & (optional) downloadlink
document.getElementById("db_backup_result").style.display = 'block';
}
}
});
});
Java-Servlet:
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String type = request.getParameter("type");
if(null != type)switch (type) {
case "db_backup":
ServletOutputStream out = response.getOutputStream();
// Prepare multipart response
response.setContentType("multipart/x-mixed-replace;boundary=End");
// Start: First part of response ////////////////////////////////////////////////////////////////////////
// execute commandline script to backup the database
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "D:\\TEMP\\sql_dump.cmd");
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
String filename = "";
int tmp = 0;
while (true) {
line = r.readLine();
if (line == null) { break; }
// code for finding filename not optimal but works for now -> redo later on
if(tmp == 1){
filename = line.substring(line.indexOf("db_backup_"), line.indexOf('"', line.indexOf("db_backup_")) );
}
else{
line = line.replace("\u201E", "\'"); // replaces the lowercase " (DOUBLE LOW-9 QUOTATION MARK)
line = line.replace("\u201C", "\'"); // replaces the uppercase " (LEFT DOUBLE QUOTATION MARK)
}
out.println(line);
tmp++;
}
// End: First part of response ////////////////////////////////////////////////////////////////////////
// Separator of firt & second part
out.println("--End");
out.flush();
// Add filename in response (name of download file)
out.println("--sql_d_fns--"); // separator for filename (used to extract filename from response data)
out.println(filename);
out.println("--sql_d_fne--"); // separator for filename (used to extract filename from response data)
// Start: Second part of response ////////////////////////////////////////////////////////////////////////
out.println("--sql_d_s--"); // separator for content of db-dump (this is the text thats going to be downloaded later on)
String filepath = "D:\\TEMP\\sql_dump\\";
FileInputStream fileInputStream = new FileInputStream(filepath + filename);
int i;
while ((i = fileInputStream.read()) != -1) {
out.write(i);
}
out.println("--sql_d_e--"); // separator for content of db-dump (this is the text thats going to be downloaded later on)
// End: Second part of response ////////////////////////////////////////////////////////////////////////
// End the multipart response
out.println("--End--");
out.flush();
break;
default:
break;
}
}
postgreSQL dump contain "lowercase" & "uppercase" quotation marks which I had to replace. I put a link to each here in case someone struggles with them as well. They have multiple encodings for those characters listed there.
Unicode Character 'DOUBLE LOW-9 QUOTATION MARK' (U+201E)
Unicode Character 'LEFT DOUBLE QUOTATION MARK' (U+201C)

Call MVC action method by javascript but not using AJAX

I have a MVC3 action method with 3 parameters like this:
var url = "/Question/Insert?" + "_strTitle='" + title + "'&_strContent='" + content + "'&_listTags='" + listTags.toString() + "'";
and I want to call this by normal javascript function not AJAX (because it's not necessary to use AJAX function)
I tried to use this function but it didn't work:
window.location.assign(url);
It didn't jump to Insert action of QuestionController.
Is there someone would like to help me? Thanks a lot
This is more detail
I want to insert new Question to database, but I must get data from CKeditor, so I have to use this function below to get and validate data
// insert new question
$("#btnDangCauHoi").click(function () {
//validate input data
//chủ đề câu hỏi
var title = $("#txtTitle").val();
if (title == "") {
alert("bạn chưa nhập chủ đề câu hỏi");
return;
}
//nội dung câu hỏi
var content = GetContents();
content = "xyz";
if (content == "") {
alert("bạn chưa nhập nội dung câu hỏi");
return;
}
//danh sách Tag
var listTags = new Array();
var Tags = $("#list_tag").children();
if (Tags.length == 0) {
alert("bạn chưa chọn tag cho câu hỏi");
return;
}
for (var i = 0; i < Tags.length; i++) {
var id = Tags[i].id;
listTags[i] = id;
//var e = listTags[i];
}
var data = {
"_strTitle": title,
"_strContent": content,
"_listTags": listTags.toString()
};
// $.post(url, data, function (result) {
// alert(result);
// });
var url = "/Question/Insert?" + "_strTitle='" + title + "'&_strContent='" + content + "'&_listTags='" + listTags.toString() + "'";
window.location.assign(url); // I try to use this, and window.location also but they're not working
});
This URL call MVC action "Insert" below by POST method
[HttpPost]
[ValidateInput(false)]
public ActionResult Insert(string _strTitle, string _strContent, string _listTags)
{
try
{
//some code here
}
catch(Exception ex)
{
//if some error come up
ViewBag.Message = ex.Message;
return View("Error");
}
// if insert new question success
return RedirectToAction("Index","Question");
}
If insert action success, it will redirect to index page where listing all question include new question is already inserted. If not, it will show error page. So, that's reason I don't use AJAX
Is there some one help me? Thanks :)
Try:
window.location = yourUrl;
Also, try and use Fiddler or some other similar tool to see whether the redirection takes place.
EDIT:
You action is expecting an HTTP POST method, but using window.location will cause GET method. That is the reason why your action is never called.
[HttpPost]
[ValidateInput(false)]
public ActionResult Insert(string _strTitle, string _strContent, string _listTags)
{
// Your code
}
Either change to HttpGet (which you should not) or use jQuery or other library that support Ajax in order to perform POST. You should not use GET method to update data. It will cause so many security problems for your that you would not know where to start with when tackling the problem.
Considering that you are already using jQuery, you might as well go all the way and use Ajax. Use $.post() method to perform HTTP POST operation.
Inside a callback function of the $.post() you can return false at the end in order to prevent redirection to Error or Index views.
$.post("your_url", function() {
// Do something
return false; // prevents redirection
});
That's about it.
You could try changing
var url = "/Question/Insert?" + "_strTitle='" + title + "'&_strContent='" + content + "'&_listTags='" + listTags.toString() + "'";
to
var url = "/Question/Insert?_strTitle=" + title + "&_strContent=" + content + "&_listTags=" + listTags.toString();
I've removed the single quotes as they're not required.
Without seeing your php code though it's not easy to work out where the problem is.
When you say "It didn't jump to Insert action of QuestionController." do you mean that the browser didn't load that page or that when the url was loaded it didn't route to the expected controller/action?
You could use an iframe if you want to avoid using AJAX, but I would recommend using AJAX
<iframe src="" id="loader"></iframe>
<script>
document.getElementById("loader").src = url;
</script>

Categories

Resources