0

I am trying to retrieve a QR code image path that is in binary form from a SQL database, then insert that as a full image into the email using MailMessage and SmtpClient.

I understand that we would have to convert the base 64 string into an image file, so that it can be visualized. But I am currently having no clues as to how to do this. Is there any simple explanation or coding examples that I can refer to?

Below is my code for retrieving the QR code image path from the SQL database

 //retrieve QR Code image 
string getQRimage = "SELECT QRCode FROM Parcel WHERE ConsignmentNum =@num";
SqlCommand cmdGetQR = new SqlCommand(getQRimage, conn);
cmdGetQR.Parameters.AddWithValue("@num", txtConsignmentNum.Text);

SqlDataReader dr1 = cmdGetQR.ExecuteReader();
bool recordFound1 = dr1.Read();
if (recordFound1)
{
    byte[] bytes = (byte[])cmdGetQR.ExecuteScalar();
    string strBase64 = Convert.ToBase64String(bytes);
    Image1.ImageUrl = "data:Image/png;base64," + strBase64;
}

What I am trying to do is to send Image1 in the email body. The coding for the email is as below:

//send email 
try
{
    //retrieve student email 
    if (conn.State == System.Data.ConnectionState.Closed)
    {
        conn.Open();

        string getEmail = "SELECT Email FROM Student WHERE StudentID='" + txtStudentID.Text + "'"; 
        SqlCommand cmdGetMail = new SqlCommand(getEmail, conn);
        cmdGetMail.Parameters.AddWithValue("@StudentID", txtStudentID.Text);


        SqlDataReader dr = cmdGetMail.ExecuteReader();
        bool recordFound = dr.Read();
        if (recordFound)
        {
            lblStudentEmail.Text = dr["Email"].ToString();
            lblStudentName.Text = dr["StudentName"].ToString();
        }
    }

    MailMessage mailMessage = new MailMessage();
    mailMessage.From = new MailAddress("contact.now.testing@gmail.com");
    mailMessage.To.Add(lblStudentEmail.Text);
    mailMessage.IsBodyHtml = true; 
    mailMessage.Subject = "Parcel" + txtConsignmentNum.Text + "Available for Pick Up";
    mailMessage.Body = "Hi " + "sample text" + Image1;

    SmtpClient smtpClient = new SmtpClient();
    smtpClient.Host = "smtp.gmail.com"; 
    smtpClient.Port = 587;
    smtpClient.EnableSsl = true;
    smtpClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
    smtpClient.UseDefaultCredentials = false; 
    smtpClient.Credentials = new System.Net.NetworkCredential("email", "password");
    smtpClient.Send(mailMessage);
    Response.Write("<script>alert('Your email has been sent!')</script>");
}
catch (Exception ex)
{
    throw; 
    // Response.Write("<script>alert('Your email could not be sent successfully due to error found: " + ex.ToString() + "')</script>");
}

Please let me know if there is any solution or suggestion to this.

Drag and Drop
  • 2,672
  • 3
  • 25
  • 37
irene
  • 15
  • 7
  • You are trying to inline the image in the email body ? – Drag and Drop Mar 02 '21 at 14:45
  • Related : [C# sending mails with images inline using SmtpClient](https://stackoverflow.com/questions/1212838/), [Send inline image in email](https://stackoverflow.com/questions/18358534), [Add multiple images in the email body (inline)](https://stackoverflow.com/questions/33665280/) – Drag and Drop Mar 02 '21 at 14:47
  • yes! that would be what i have in mind, but adding it as an attachment would be fine too. – irene Mar 02 '21 at 14:47
  • Why do you have all that logic within an in block checking to see if the connection is closed or not? You shouldn't need to check it, and even if you did, the rest of the logic shouldn't be in that if block. Think about how you structure your code more - put more thought into what needs to be done and when it makes sense to do it. – mason Mar 02 '21 at 14:48
  • I have read through the related posts, and I can't seem to understand how to tweak it to my code as my image path is stored inside the database and I would have to convert it to base64 first. And then inline it into the email body. That's the part I'm most confused about. – irene Mar 02 '21 at 14:51
  • @mason I have been taught to code that way so it's just what I went with..that we should always check if the connection is open or not. – irene Mar 02 '21 at 14:52
  • 2
    No, no you should not. For example, did you just open the connection already? Then checking if it's closed again is pointless. Did you just create the connection? Then you can assume it's closed. Since you the connection class implements [IDisposable](https://learn.microsoft.com/en-us/dotnet/api/system.idisposable?view=net-5.0) you shouldn't be using a single connection outside of a single method anyways. And still - the rest of the logic in your if statement doesn't belong there - you need to execute that regardless of the prior state of the connection. – mason Mar 02 '21 at 14:56
  • 3
    Also - your code is vulnerable to a [SQL Injection attack](https://bobby-tables.com/). I realize you're a student and this isn't a real application for consumption, but you should learn best practices now when it comes to security, rather than falling into bad habits. I suggest you [fix it](https://bobby-tables.com/adodotnet). Use a parameterized query to execute your SQL, don't form your query via string concatenation. Imagine what would happen is someone entered a value of `' DROP TABLE Students;--` for `txtStudentID.Text`. – mason Mar 02 '21 at 15:00
  • You can either serve the image as pure html using `My Image` Or pass tat byte arry to a memory stream. `var stream = new MemoryStream(byteArray);` and pass that stream to an Attachemnt `mail.Attachments.Add(new System.Net.Mail.Attachment(stream, "test.jpeg"));`. and use using on MailMessage and SMTP client – Drag and Drop Mar 02 '21 at 15:19
  • You've already been told to not use [addwithvalue](http://www.dbdelta.com/addwithvalue-is-evil/). Learn and develop good habits – SMor Mar 02 '21 at 16:07
  • You don't need to execute the query twice, i.e. `byte[] bytes = (byte[])cmdGetQR.ExecuteScalar();` is unnecessary. You already have a reader, `dr1`, which just read the row and has the value *right there*. Use `byte[] bytes = (byte[])dr1[0]` instead. – madreflection Mar 02 '21 at 16:33

0 Answers0