Solved

.net Mail

Posted on 2008-10-21
13
331 Views
Last Modified: 2012-05-05
I am sending html emails from a windows form application the email is a table which which has all style contenet inline, this works fine if the recipient is using outlook if I test send the email to a msn email account the image appears as a grey square, If I forward the email from outlook to a msn account the image appears as it should! The code looks like the following:

Dim htmlContent1 As String = "<table border=""1"" bordercolor=""#000000"" cellpadding=""5"" cellspacing=""0"" style=""color: #ffffff; font-family: Arial Bold; vertical-align: middle; width: 600px; text-align: left""><td bgcolor=""#000000"" colspan=""2""><MARQUEE bgcolor=#000000 loop=-1 scrollamount=2 width=100%>My Message!!!!</MARQUEE></td></tr><tr><td colspan=""2""><span style=""color: #000000;font-size: 10pt; font-family: Arial"">" & txthtml & "</span></td></tr><tr><td colspan=""2"">"
            Dim htmlContent2 As String = "<img src=cid:companylogo><BR/><A HREF='" & URLtxt & "'>Visit&copy Key</A>"
            Dim htmlContent3 As String = "</td></tr><tr><td style=""width: 100px""><span style=""color: #000000; font-family: Arial Bold; font-size: 10pt; vertical-align: top; text-align: left"">" & ColDetail & "</span></td><td style=""width: 100px""><span style=""color: #000000; font-family: Arial Bold; font-size: 10pt; vertical-align: top; text-align: left"">" & DelDetail & " </span></td></tr><tr><td bgcolor=""#000000"" colspan=""2""><span style=""color: #ffffff; font-family: Arial"">Message sent " & Now() & "</span></td></tr></table>"

            Dim htmlView As System.Net.Mail.AlternateView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(htmlContent0 + htmlContent1 + htmlContent2 + htmlContent3, Nothing, "text/html")

            Dim logo As New LinkedResource("C:\images\EmailBanner.gif")
            logo.ContentId = "companylogo"

            htmlView.LinkedResources.Add(logo)

            'Me.WebBrowser1.Url = htmlView

            mail.AlternateViews.Add(htmlView)

            Dim smtp As New System.Net.Mail.SmtpClient("0.0.0.0")

Anyone tell me how to overcome this issue?

Regards,
JoeBo747
0
Comment
Question by:JoeBo747
  • 6
  • 4
  • 3
13 Comments
 
LVL 7

Expert Comment

by:talker2004
ID: 22768097
Is it possible to host the image as opposed to embedding it.

Also make sure that you have your hotmail account set to display images.

0
 
LVL 10

Expert Comment

by:jinn_hnnl
ID: 22768188
Make sure all of your html has to be in correct format, for example brreak line should be
<br /> instead of <br/>

you can just have to put single quote instead of double quote like that
<table border='1' bordercolor='#000000'

a lot of these atrributes won't  be supported by email client so make sure you stick to the most comment one and email supportive

Try to redo it first

JINN

cssForEmail3--CSS-property-.JPG
0
 
LVL 7

Expert Comment

by:talker2004
ID: 22768517
I would create an external html file and edit it through the ide or an html editor. At that point read the file in as a string. This is the easiest way to merge an html email doc.
0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
LVL 7

Expert Comment

by:talker2004
ID: 22768563
Here is some code snippets from a sample program i developed. Reading the html file into your string is more flexible because you can run html validation on your html markup.


 Public Function MergeEmail(ByVal emailIdentifier As String) As String
        Dim FeedBackURL As String
        FeedBackURL = _
        System.Configuration.ConfigurationManager.AppSettings("FeedBackEmailURL").ToString()

        Dim strEmailContent As String = ""

        Try
            Dim objIO As New IOLib
            Dim FileBytes As Byte() = objIO.RetrieveServerFileBytes(FeedBackURL, "", "", "")
            If Not IsNothing(FileBytes) Then
                strEmailContent = objIO.ConvertBytesToString(FileBytes)
                strEmailContent = strEmailContent.Substring(3)
            End If
            objIO = Nothing
 
            strEmailContent = strEmailContent.Replace("#ContactFName#", txtFName.Value)
            strEmailContent = strEmailContent.Replace("#ContactLName#", txtLName.Value)
            strEmailContent = strEmailContent.Replace("#ContactEmail#", txtEmail.Value)
            strEmailContent = strEmailContent.Replace("#ContactMessage#", txtFeedBack.Value)
            strEmailContent = strEmailContent.Replace("#EmailIdentifier#", emailIdentifier)
        Catch ex As Exception

        End Try
 
        Return strEmailContent
 
    End Function
Imports Microsoft.VisualBasic
Imports System.Net
Imports System.IO
 
Public Class IOLib
 
 
    Public Function RetrieveServerFileBytes(ByVal SourceURL As String, Optional ByVal UserName As String = "", Optional ByVal Password As String = "", Optional ByVal Domain As String = "") As Byte()
 
        Try
 
            Dim wr As HttpWebRequest = _
            CType(WebRequest.Create(SourceURL), HttpWebRequest)
 
            Dim cr As New System.Net.NetworkCredential
            cr.UserName = UserName
            cr.Password = Password
            cr.Domain = Domain
            wr.Credentials = cr
 
            Dim ws As HttpWebResponse = CType(wr.GetResponse(), HttpWebResponse)
            Dim str As Stream = ws.GetResponseStream()
            Dim inBuf(100000) As Byte
            Dim bytesToRead As Integer = CInt(inBuf.Length)
            Dim bytesRead As Integer = 0
            While bytesToRead > 0
                Dim n As Integer = str.Read(inBuf, bytesRead, bytesToRead)
                If n = 0 Then
                    Exit While
                End If
                bytesRead += n
                bytesToRead -= n
            End While
            Return inBuf
 
        Catch ex As Exception
 
            Return Nothing
        End Try
    End Function
 
    Public Function ConvertBytesToString(ByVal BytesToConvert As Byte()) As String
        Try
            Dim dBytes As Byte() = BytesToConvert
            Dim str As String
            Dim enc As New System.Text.ASCIIEncoding()
            str = enc.GetString(dBytes)
            Return str
        Catch ex As Exception
            Return ""
        End Try
    End Function
 
End Class

Open in new window

0
 
LVL 1

Author Comment

by:JoeBo747
ID: 22769366
Hi ,
Thanks for both of your replies, there is quite a bit here to take on please bear with me, talker2004 your sample code uses: System.Configuration.ConfigurationManager.AppSettings("FeedBackEmailURL").ToString()
I get an error: ConfigurationManager is not a member of Configuration was the code written for an asp page? To run this code do I save the email with place holders as in your code #ContactFName# as a html file and then call MergeEmail(ByVal emailIdentifier As String) and pass the file name and path into the  into the variable emailIdentifier ?
Regards,
JoeBo747
0
 
LVL 7

Expert Comment

by:talker2004
ID: 22769446
I am on my blackberry right now at lunch when I get back I will try to give a better answer. You can add a reference to configuration manager and add the seitting to your config file. Or simply replace that line with a hard coded path to the html file.
0
 
LVL 7

Accepted Solution

by:
talker2004 earned 300 total points
ID: 22769880
JoeBo, the email identifier was a custom job, it actually merged a unique identifier into a querystring which was part of an image tag. When the user opened the email my server was able to log in a database taht the user opened the email.

I will rework the routine below for you to better suit your purpose.

Now with this modification you can pass through

"http://mydomain.com/myemailmergebasefile.html"

I was pulling it from the configuration file.
Public Function MergeEmail(ByVal FeedbackURL As String) As String
         
        Dim strEmailContent As String = ""
 
        Try
            Dim objIO As New IOLib
            Dim FileBytes As Byte() = objIO.RetrieveServerFileBytes(FeedBackURL, "", "", "")
            If Not IsNothing(FileBytes) Then
                strEmailContent = objIO.ConvertBytesToString(FileBytes)
                strEmailContent = strEmailContent.Substring(3)
            End If
            objIO = Nothing
 
            strEmailContent = strEmailContent.Replace("#ContactFName#", txtFName.Value)
            strEmailContent = strEmailContent.Replace("#ContactLName#", txtLName.Value)
            strEmailContent = strEmailContent.Replace("#ContactEmail#", txtEmail.Value)
            strEmailContent = strEmailContent.Replace("#ContactMessage#", txtFeedBack.Value)
            strEmailContent = strEmailContent.Replace("#EmailIdentifier#", emailIdentifier)
        Catch ex As Exception
 
        End Try
 
        Return strEmailContent
 
    End Function

Open in new window

0
 
LVL 7

Expert Comment

by:talker2004
ID: 22769917


So in the html file you might have,


Hello, #ContactFName# how are you today.

<img src="http://mydomainname.com/myimagefile.jpg alt="my image"/>

Obviously the code i posted above will read in the merged html document which will be sent to the user.
0
 
LVL 1

Author Comment

by:JoeBo747
ID: 22775573
Hi talker2004,

Thank you for sharing your code, I have followed your suggestions and have a html file which looks like the code snippet below. I am able to replace the place holders with the content in every instance apart from the image which in the html editor is visible as an image. Can you spot my mistake?

regards,
JoeBo747

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 
<head>
<meta http-equiv="Content-Language" content="en-us" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>HTMLBase</title>
<style type="text/css">
.style2 {
	border-style:none;
	background-color:white;
	vertical-align: top;
	text-align: left;
	width: 50%;
	padding: 5;
}
.style3 {
	border-collapse: collapse;
	background-color:white;
	padding: 0;
}
 
.style4 {
	border-collapse: collapse;
	background-color: black;
	color: #FFFFFF;
}
 
</style>
</head>
 
<body>
 
<table style="width: 600px; height: 500px">
	<tr>
		<td colspan="2" class="style4"><strong>#marquee#</strong></td>
	</tr>
	<tr>
		<td style="height: 249px" colspan="2" class="style2"><strong>#salutation#</strong><br />
		<br />
		#body#</td>
	</tr>
	<tr>
		<td colspan="2" class="style3" style="height: 38px">
		<img src="http://localhost/webmail/EmailBanner.gif" alt="Banner" /><br />
<center >#href#</center></td>
	</tr>
	<tr>
		<td class="style2" style="height: 106px"><strong>Collection:<br />
		</strong>#collect#</td>
		<td class="style2" style="height: 106px"><strong>Delivery:</strong><br />
		#deliver#</td>
	</tr>
	<tr>
		<td colspan="2" class="style4">#timestamp#</td>
	</tr>
</table>
 
</body>
 
</html>

Open in new window

0
 
LVL 10

Assisted Solution

by:jinn_hnnl
jinn_hnnl earned 200 total points
ID: 22775634
You can implement the same idea, but you have to use inline css (instead of class="style4" you will have to set style specificly.

Mail client like Gmail or some another doesn't accept predefined css but inline css
so you might have to go:

<td colspan="2" style="background-color: black; color: #FFFFFF;"> <-this should work for most email client ... very supportive like Yahoo, hotmail ... to very basic like Gmail.

In my 1st post I have a list of CSS reference which refer to CSS support of each mail client. Check that and you might know why some css doesn't work

JINN

0
 
LVL 1

Author Comment

by:JoeBo747
ID: 22777662
Hi,

Thanks for the reply, I will check this out and get back.
Regards,
JoeBo
0
 
LVL 1

Author Closing Comment

by:JoeBo747
ID: 31508312
Hi,
That appears to be the answer, I would like to thank you both for your support hopefully you will agree to a share of the points based on the replies.
Thanks again,
JoeBo
0
 
LVL 10

Expert Comment

by:jinn_hnnl
ID: 22794052
Glad you worked it out. I have no problem with your shared given marks.

^^

Glad to help

JINN
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question