An image to be displayed inline in a JavaMail created message shows up twice in Apple Mail – but not Outlook? - jakarta-mail

An image to be displayed inline in a JavaMail created message shows up twice in Apple Mail – but not Outlook?
EmailMaster sends a test email message that includes:
1) an image sent with the email to be displayed inline in the title when the message is opened
2) a link to an image that has to be downloaded from a remote URL after the message is displayed.
The goal is for the message to be fully rendered when it is opened (owl). Not require the reader download it before seeing full message.
The code below works perfectly when the message is opened in a client like Outlook.
-- the Owl image displayed in line when its opened, and
-- the underline must be downloaded.
When AppleMail opens the message the Owl is displayed twice. The screen show:
-- the owl as a standalone image,
-- then the message with the owl correctly displayed in the Title.
I can’t post a screen shot, but I put a screen shot of the AppleMail screen at
http://america-3.org/images/shot.jpg
Can anyone point me to the cause of the problem? Or a solution?
HTML code added as one MimeBodyPart.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link href="cid:fonts" rel="stylesheet" type="text/css" />
<style type="text/css">
<!--
.text-blue-12 {font-family: Verdana, Arial, Helvetica, sans-serif;
text-decoration: none; font-weight: normal;
font-size:12pt; color: #0F0F0F}
body { margin: 0; padding: 0; background-color: #1A4576; width: 480px;}
tr {width:100%; background-color: white;}
-->
</style>
</head>
<body>
<table width='480px' cellspacing='0' cellpadding='6' class='text-blue-12' align="center">
<tr><td style='text-align: center;'>
Hello! <img src='cid:owl'>
</td></tr>
<tr><td style='text-align: center;'>
<img align="center" alt="Shadow" class="kmImage"
src="https://d3k81ch9hvuctc.cloudfront.net/assets/email/bottom_shadow_444.png"
width="600" style="border: 0; height: auto; line-height: 100%;
outline:none; text-decoration: none; max-width: 100%; padding-bottom: 0;
display: inline; vertical-align: bottom" />
</td></tr>
<tr><td>
This is test # 1005. The Table should be a 480px wide and centered.
If not there is a problem.
</td></tr>
<tr><td>
Yours truly,
GLB
</td></tr>
</table>
</body>
</html>
Extract of Java Class I use to test JavaMail code
public class EmailMaster {
/* JavaMail attempts to use IPv6 to connect. Windows IPv4.
* The error message will be "Network Unreachable: Connect.
* To fix it, I ran this code from the command window
* setx _JAVA_OPTIONS -Djava.net.preferIPv4Stack=true
* I tried to set _JAVA_OPTIONS as an environment variable but that didn't
* work.
*/
/* the constructor instantiates EmailMaster.
* It parses a ".properties" text file that provides the everything
* needed to define a message:
* -- send from, reply to, subject etc. Strings
* -- local paths to one or more files:
* .. a text file containing the to addresses.
* .. the HTML file that holds the message body,
* .. one of more images to be displayed inline
* in the HTML message body. I used one.
* .. one or more files to be attached to the msg. I used one.
*/
/* then it calls sendEmail() to read through the list of addresses
* and sends an individual email to each address*/
sendEmail () {
/*this section of code is done once. */
Session session = Session.getInstance(this.sessionParameters);
SMTPTransport tr = new SMTPTransport(session, new URLName (host));
tr.connect(...); // this is successful
/* the method loops through this section for every to address provided*/
Message msg = new MimeMessage(session);
msg.setReplyTo(this.replyToAddress);// read from properties file
msg.setSentDate(new java.util.Date());// read from properties file
msg.setSubject(this.subject);// read from properties file
msg.setFrom(this.fromAddress);// read from properties file
msg.setRecipient(RecipientType.TO, singleToAddress);// read from properties file
MimeMultipart mmp = new MimeMultipart();
/* add a MimeBodyPart for each image be displayed inline the HTML text */
for (MimeBodyPart part : this.imagesBodyParts.values()) {
mmp.addBodyPart(part);
/* add a MimeBodyPart for each HTML page in the message. */
for (MimeBodyPart part : this.attachmentBodyParts.values()) {
mmp.addBodyPart(part);
}
mmp.addBodyPart(this.msgPart);
msg.setContent(mmp);
msg.saveChanges();
tr.sendMessage(msg, msg.getAllRecipients());
}
}

There's a limit to how much control you have over how mail readers display messages. In the end, you may not be able to accomplish what you're trying to do with all mail readers. That said, there's some issues with the code you posted...
You've got a double nested "for" loop that first adds an image body part, then adds a bunch of attachment (html?) body parts, then sends the message, then adds more of both to the same message, then sends the message again, and so on. Surely this isn't what you intended.
If you want the message to include a single html part and some image parts that are referenced by the html part, you need to create a multipart/related message, and the image parts need Content-ID headers. This JavaMail FAQ entry will point you in the right direction.
Finally, you should never be calling the constructor for SMTPTransport directly. Instead, you should use the Session.getTransport method.

Related

Need explanation with Icecast URL authentication

Foreword: I am stuck due to poor coding skills and a lack of understanding of the details of the URL authentication. I am not a coder but an amateur who usually get by with a little help from Google.
Challenge 1:
I am trying to set Icecast up in such a way that the audio stream can only be heard when you log in to my website. The method is called URL authentication by Icecast. Here is the link to the official documentation:
https://icecast.org/docs/icecast-2.4.0/auth.html
My problem: I understand that I have to integrate certain queries in the icecast.xml that are then answered by the player on my website. Unfortunately, I don't know where to integrate these codes. In a file in the webroot? In the header of the player page?
Challenge 2:
Another thing is that the player is working, but when I hit the pause button and restart the player 10 minutes later the song picks up there I paused the player even though the radio stream is already 2 titles ahead. So the cover art does not match the audio.
I guess that also has something to do with certain tweaks in the icecast.xml. Again ... I don't know how to add these tweaks and how to address them on my website (same issue as with the authentication).
Due to royalty issues, my website is behind a firewall for the time being.
Can anyone shed some light on my questions?
I included the code of my icecast.xml and of the iFrame that contains the player.
Best wishes,
Paul
This is the iFrame that contains the Drupal website and the HTML5 player:
<html>
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
<meta name=viewport content="width=device-width, initial-scale=1">
<style type="text/css">
html, body {
background: #333333;
height: 100%;
margin: 0px;
padding: 0px;
border: 0px;
}
iframe {
width: 100%;
height: 92%;
margin: 0px;
padding: 0px;
border: none;
display: block;
}
</style>
<body>
<?php
print('<iframe id="drupal_site" src="http://test.zoootradio.com" height="92%" width="100%" frameborder="0"></iframe>');
header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1.
header("Pragma: no-cache"); // HTTP 1.0.
header("Expires: 0"); // Proxies.
print('<audio id="player" controls>');
print('<source src="http://192.168.2.50:8000/zr.mp3" type="audio/mpeg">');
print('</audio>');
?>
</body>
</html>
This is my icecast.xml file:
<icecast>
<location>Earth</location>
<admin>icemaster#localhost</admin>
<limits>
<clients>15</clients>
<sources>1</sources>
<queue-size>524288</queue-size>
<client-timeout>30</client-timeout>
<header-timeout>15</header-timeout>
<source-timeout>10</source-timeout>
<burst-on-connect>1</burst-on-connect>
<burst-size>65535</burst-size>
</limits>
<authentication>
<!-- Sources log in with username 'source' -->
<source-password>XXXXXXX</source-password>
<!-- Relays log in with username 'relay' -->
<relay-password>XXXXXXX</relay-password>
<!-- Admin logs in with the username given below -->
<admin-user>XXXXXXX</admin-user>
<admin-password>XXXXXXX</admin-password>
</authentication>
<hostname>192.168.2.50</hostname>
<!-- You may have multiple <listener> elements -->
<listen-socket>
<port>8000</port>
<!-- <bind-address>127.0.0.1</bind-address> -->
<!-- <shoutcast-mount>/stream</shoutcast-mount> -->
</listen-socket>
<http-headers>
<header name="Access-Control-Allow-Origin" value="*" />
</http-headers>
<mount type="normal">
<mount-name>/zr.mp3</mount-name>
<authentication type="url">
<option name="stream_auth" value="http://test.zoootradio.com/player"/>
</authentication>
</mount>
<fileserve>1</fileserve>
<paths>
<!-- basedir is only used if chroot is enabled -->
<basedir>/usr/share/icecast2</basedir>
<!-- Note that if <chroot> is turned on below, these paths must both
be relative to the new root, not the original root -->
<logdir>/var/log/icecast2</logdir>
<webroot>/usr/share/icecast2/web</webroot>
<adminroot>/usr/share/icecast2/admin</adminroot>
<!-- <pidfile>/usr/share/icecast2/icecast.pid</pidfile> -->
<alias source="/" destination="/status.xsl"/>
<!-- The certificate file needs to contain both public and private part.
Both should be PEM encoded.
<ssl-certificate>/usr/share/icecast2/icecast.pem</ssl-certificate>
-->
</paths>
<logging>
<accesslog>access.log</accesslog>
<errorlog>error.log</errorlog>
<!-- <playlistlog>playlist.log</playlistlog> -->
<loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
<logsize>10000</logsize> <!-- Max size of a logfile -->
<!-- If logarchive is enabled (1), then when logsize is reached
the logfile will be moved to [error|access|playlist].log.DATESTAMP,
otherwise it will be moved to [error|access|playlist].log.old.
Default is non-archive mode (i.e. overwrite)
-->
<!-- <logarchive>1</logarchive> -->
</logging>
<security>
<chroot>0</chroot>
<!--
<changeowner>
<user>nobody</user>
<group>nogroup</group>
</changeowner>
-->
</security>
1 - "URL auth"
Your icecast.xml does not contain any definition, so you don't have URL-auth configured.
What are you really trying to achieve?
2 - pause
Streams can't be paused, don't try to do it, it will break things. If you stop a stream, make sure that you do it in a way that makes the browser actually drop the connection.
Also you should always use a 'cache buster' or other way to ensure that the browser does not try to use cached stream content. (See my other answers on related topics here)

primefaces show contextmenu on mobile devices

I've searched a lot but I can't hit the answer, my problem is that I have a datatable with a context menu. On desktop I have no problem, it shows up on right click, but on mobile devices I can't get it to work: when I tap and hold the row it selects the nearest text and shows up the browser's context menu.
I've tried a lot of things:
Adding a css class style:
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome and Opera */
}
and the implementation as:
<p:dataTable id="lista" widgetVar="lista" var="unElem" ...>
<p:column headerText="Column 1" styleClass="noselect">
<h:outputText value="#{unElem.codigo}"/>
</p:column>
</p:dataTable>
<p:contextMenu for="lista" id="context" model="#{view.modeloMenuContextual}"/>
Searching on the web about the "event" attribute of the p:contextMenu and found that the default event is "contextmenu", so if you need other events you can add them space separated. The other event I found was "click", but I don't need it
<p:contextMenu model="#{view.modeloMenuContextual}" event="click contextmenu"/>
Searching in the official documentation (web and pdf) (https://www.primefaces.org/showcase/)
Searching in Primefaces' code in github (https://github.com/primefaces/primefaces)
I'm working with PrimeFaces 6.2
Hope anybody can help me.
Thanks!

Displaying code chunks in a frame in hugo using blogdown

I have recently created a blog post using blogdown and hugo. I was able to add code folding but the code appears like regular text on the website. I am trying to display the code in a frame or something distinguishing it from the rest of the text ex:
I have tried everything but could not figure how to do it. I am guessing it has to deal something with the theme I am using. I am using Hugo Nuo.
You can find the current shape of the blog post here:
https://www.staturk.xyz/post/poll-accuracy-in-turkish-elections/
Here is the beginning of my .rmd file for the post where I am trying to display the code in a frame:
---
title: "Poll Accuracy in Turkish Elections"
date: '2018-12-25'
slug: poll-accuracy-in-turkish-elections
tags:
- Polls
- Politics
- R
categories:
- Turkish Politics
- Rstats
---
```{r, echo=FALSE}
htmltools::includeHTML("~/Documents/Personal/Projects/Blog/Turkstat/content/media/posts/header.html")
```
```{r echo = F, results='hide', message=FALSE}
library(tidyverse)
library(plyr)
library(stringr)
library(scales)
library(knitr)
```
There are two steps here - figuring out what to style and then adding the style to the theme.
Figuring out what to style
Looking at the raw html for the post (ctrl-U in Chrome), the code fragments are wrapped in a <pre class="r"><code>..</code></pre> tag set. So, we could give it a border (for instance) by adding the following to the html header :
<style>
pre.r {
border-style: solid;
border-width: 2px;
}
</style>
Adding to the theme
Looking at the theme code, the best way to accomplish this seems to be to override the head partial in themes/{theme_name}/layouts/partials/head.html. Copy that file up into the the same area of the site folder. The following commands will do the trick if you are on linux:
cd $sitedir
mkdir -p layouts/partials
cp themes/hugo-nuo/layouts/partial/head.html layouts/partial
Then edit the copy of the file to add the above style fragment.

Formatting ng-init text inside input tag - AngularJS

I am having ng-init defined in my input tag. I would like to have this input in the specified format with line breaks.
I tried using <pre> tags and white-space:pre-line property too. But this seems not to get sorted.
<div style="font-family: Poppins !important;-webkit-font-smoothing: antialiased;top:35%; position:absolute; width: 100%; background:transparent !important; margin-bottom:0rem !important">
<input class="form-control"
id="volunteerCallTextId" type="text" placeholder="Volunteer Call Text"
ng-model="volunteerCallText"
ng-init="volunteerCallText ='Hello, may I speak to (Insured). Hi (Mr., Mrs. Etc), my name is _________.
I am with xxx Insurance and am calling you about the recent fire/flood/weather event in_____.
We are calling to check and see if your family is safe and let you know that xxx is here for you.
I want to let you know that we have emergency claims locations set up at: (use locations below).
Or you can call our Claims center at 888....Please be aware that.....'"
style="width: 75em; height:25em; white-space:pre-line" />
</div>
Format expected:
Hello, may I speak to (Insured). Hi (Mr., Mrs. Etc), my name is
_________.
I am with xxx Insurance and am calling you about the recent fire/flood/weather event in_____. We are calling to check and
see if your family is safe and let you know that xxx is here for you.
I want to let you know that we have emergency claims locations set up
at: (use locations below). Or you can call our Claims center at
888....Please be aware that.....
Can someone suggest what could be done?
I am not sure it can be done in input box or not but it works like this in textarea please try and let me know if t helps you
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="" >
<div style="font-family: Poppins !important;-webkit-font-smoothing: antialiased;top:35%; position:absolute; width: 100%; background:transparent !important; margin-bottom:0rem !important">
<textarea class="form-control"
id="volunteerCallTextId" style="width:75em; height:25em; white-space: pre-wrap;" type="text" placeholder="Volunteer Call Text"
ng-model="volunteerCallText"
ng-init="volunteerCallText ='Hello, may I speak to (Insured). Hi (Mr., Mrs. Etc), my name is _________ \n\
I am with xxx Insurance and am calling you about the recent fire/flood/weather event in_____.\n\
We are calling to check and see if your family is safe and let you know that xxx is here for you.I want to let you know that we have emergency claims locations set up at: (use locations below).Or you can call our Claims center at 888....Please be aware that.....'"
></textarea>
</div>
</div>
</body>
</html>

Calling Google Apps Script as webapp from AppEngine returns 405

I have issues when I try to call a GAPPS script that is published as a webapp. I am trying to call this service from AppEngine. I am doing a POST method to this script with a JSON Payload. Urlfetch options are set to follow redirects and a timeout of 30 secs. The script is publicly available and open to anonymous users.
On my local GAE development machine, the URLFetch response from the script is 200, and all is fine.
When I move to production, the script gets executed but returns errors and an HTML page.
I have follow redirects on on URLFetch and I have set the deadline to 30secs.
status response : 405
response text :
<!DOCTYPE html><html lang="en" ><head><meta name="description" content="Web word processing, presentations and spreadsheets"><link rel="shortcut icon" href="//ssl.gstatic.com/docs/common/drive_favicon1.ico"><title>Google Drive -- Page Not Found</title><link href="//fonts.googleapis.com/css?family=Open+Sans:300" rel="stylesheet" type="text/css"><style>/* Copyright 2014 Google Inc. All Rights Reserved. */
.goog-inline-block{position:relative;display:-moz-inline-box;display:inline-block}* html .goog-inline-block{display:inline}*:first-child+html .goog-inline-block{display:inline}#drive-logo{color:#91959c;font-family:"Open Sans",Arial,sans-serif;font-size:27px;font-weight:300;position:absolute;text-shadow:0 1px 1px white;white-space:nowrap}#drive-logo img{padding:0 0.4em 0 0;position:relative;top:2px;vertical-align:middle}#drive-logo a{color:#91959c;text-decoration:none}#drive-logo span.goog-inline-block{margin-top:2px;vertical-align:top}</style><style type="text/css">body {background-color: #fff; font-family: Arial,sans-serif; font-size: 13px; margin: 0; padding: 0;}a, a:link, a:visited {color: #112ABB;}</style><style type="text/css">.errorMessage {font-size: 12pt; font-weight: bold; line-height: 150%;}</style></head><body><div style="margin: auto; max-width: 750px;"><div style="margin: 80px 40px 20px 40px; position:relative; "><div style="position: absolute; top: -80px;"><h1 id="drive-logo"><img src="//www.google.com/images/logos/google_logo_41.png" width="116" height="41" alt="Google logo" ><span class="goog-inline-block">Drive</span></h1></div><div align="center"><p class="errorMessage" style="padding-top: 50px">Sorry, the file you have requested does not exist.</p><p> Please check the address and try again. </p><div style="background: #F0F6FF; border: 1px solid black; margin-top: 35px; padding: 10px 125px; width: 300px;"><p><strong>Get stuff done with Google Drive</strong></p><p>Apps in Google Drive make it easy to create, store and share online documents, spreadsheets, presentations and more.</p><p>Learn more at drive.google.com/start/apps.</p></div></div></div></div></body></html>
response header:Expires=Fri, 01 Jan 1990 00:00:00 GMT
response header:X-XSS-Protection=1; mode=block
response header:Alternate-Protocol=443:quic,p=0.02
response header:Set-Cookie=NID=67=KSieONzrWKqWVEt8E4M2rUo_2nooEJ6qrh80LXTppGKYQux2iGFN-BHoqn7r5Yn0F4WaYtTbXDa6y2iAa3FtRBMAn6qf526lmPkZZek7nSQUvCv4wvthsDsL4P11Yx;Domain=.googleusercontent.com;Path=/;Expires=Tue, 02-Jun-2015 23:39:38 GMT;HttpOnly
response header:X-Google-Cache-Control=remote-fetch
response header:Server=GSE
response header:Cache-Control=no-cache, no-store, max-age=0, must-revalidate
response header:Pragma=no-cache
response header:X-Content-Type-Options=nosniff
response header:X-Frame-Options=SAMEORIGIN
response header:Date=Mon, 01 Dec 2014 23:39:38 GMT
response header:P3P=CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
response header:Allow=HEAD, GET
response header:x-chromium-appcache-fallback-override=disallow-fallback
response header:Via=HTTP/1.1 GWA
response header:Content-Type=text/html; charset=utf-8
The funny - no so much - thing is that the script WORKS NEVERTHELESS most of the time but not always or not for all users.
You can see that thet response header says Allow=HEAD, GET but I implemented doPOst in my script.
Nevertheless, I have tried solving this problem by rewriting the whole things to work with GET and a parameter but I am running into similar issues !
Long story short : works perfectly and with status response 200 on GAE local development server, faulty responses and unstable behavior when deployed to GAE>
GAS is very picky when running as webapp. Sometimes it helps to put the script into a public folder on Google Drive.

Resources