Sending email notification upon error in C# - c#

I set up this try/catch and I want to send an error to my email when something goes wrong like an invalid password being entered. I know I have most of it right but I'm not getting an email when I force a change in my config file. I'm not getting any errors when I run this so I'm assuming it must be something small. Does anyone see any obvious errors I've made? Let me know if additional info is required.
Thanks in advance...learning tons of C# but no master just yet.
try
{
_arrivals = new ArrivalsService();
_configuration = new Configuration(xmlMessage);
//process summary or detail
if (_configuration.IncludeHODetails == true)
{
throw new Exception("Include HOH Details is a future feature.");
//ProcessArrivalDetails(_configuration);
}
else
ProcessArrivalSummary(_configuration);
UpdateLastRunDate(_configuration.ClientId, _configuration.LastRunDateId, DateTime.Now);
}
catch (Exception ex)
{
if (_configuration == null)
{
string[] messageTo = new[] { "aaaaaaaaaaaa#gmail.com" };
//string acctManagerEmail = Util.usp_GetEmailAcct(_clientId);
//string[] messageTo = new[] { "77777777777.com", acctManagerEmail };
EmailUtility.SendEmail(Util.EMAIL_FROM, messageTo,
"Error Running Report Utility for Client: " + _configuration.DbName, "Error Message: " + ex.Message,
Util.SMTP_SERVER, false);
}
throw new Exception("Error Occurred");
}
Here's my EmailUtility file:
namespace Common
{
public class EmailUtility
{
public static string SMTP_SERVER;
public static string[] GetEmailRecipientAdmin();
public static void SendEmail(string messageFrom, string[] messageTo, string messageSubject, string messageBody, string ipAddress, bool isHtml);
public static void SendEmail(string messageFrom, string[] messageTo, string[] messageCC, string messageSubject, string messageBody, string messageAttachmentPath, string ipAddress, bool isHtml);
public static void SendEmail(string messageFrom, string[] messageTo, string[] messageCC, string messageSubject, string messageBody, string[] messageAttachmentPath, string ipAddress, bool isHtml);
public static void SendEmail(string messageFrom, string messageTo, string messageSubject, string messageBody, string ipAddress, bool isHtml);
public static void SendEmail(string messageFrom, string messageTo, string messageSubject, string messageBody, string messageAttachmentPath, string ipAddress, bool isHtml);
}
}

Related

Check if a C# string is a well formed url with a port number

I got a string which I check if it represents a URL like this:
if(Uri.IsWellFormedUriString(urlString, UriKind.Absolute)) ...
Is there also a way to add there a check if the url contains a port number?
You could offload all the heavy work to the Uri constructor:
var uri = new Uri(urlString);
Then you only need to interpret uri.Authority. If it contains a colon, the port is specified.
public static bool IncludesPort(this string urlAddress)
{
return new Uri(urlAddress).Authority.Contains(':');
}
public class StackoverflowQuestion
{
public string Run() {
string urlString = "http://mywebsite:8001/application/api";
if (Uri.IsWellFormedUriString(urlString, UriKind.Absolute) && urlString.IncludesPort())
return "The uri contains explicitly defined port";
return "";
}
}
public static class Extensions {
public static bool IncludesPort(this string urlAddress)
{
urlAddress = urlAddress.Replace("http://", "").Replace("https://", "");
var splitted = urlAddress.Split(':');
var port = splitted?[1].Split("/")?[0];
return port != null && int.TryParse(port, out _);
}
}

C# Creating a Class List<>/Dictionary<>, writing to and reading from .txt file as a database without overwriting data

This is one of the most common questions you guys get here so forgive me but I cannot get past this no matter how hard I search.
I am building a keychain application for a project in Windows Forms Application, and for the purpose of understanding this concept as easily as possible I went with a List<> rather than Dictionary//iList
This is the Class I have been using:
public class Account
{
public static List<Account> myAccountList = new List<Account>();
public string Domain; //this is supposed to be google/skype/facebook
public string Email;
public string Username;
public string Password;
public Account (string domain, string email, string username, string password)
{
Domain = domain;
Email = email;
Username = username;
Password = password;
myAccountList.Add(new Account(domain, email, username, password)); //constructor calls the new list instance
}
private static void SaveToFile()
{
System.IO.File.WriteAllLines(#accountdb.txt, myAccountList);
}
private static void ReadFromFile() // this is meant to be used as authentication in my main form, it isn't necessary right now..
{
System.IO.File.ReadAllLines(#accountdb.txt);
}
}
I have a couple issues with this:
I cannot create a functional Save method to write to file, I have tried several methods in System.IO
When I changed the list to a one-dimensional array, it would constantly overwrite it, I want to simulate MySQL to familiarize myself for later on.
The Button Click event that calls the Constructor:
private void buttonSave_Click(object sender, EventArgs e)
{
string domain, email, username, password;
domain = comboboxDomain.Text;
email = textboxEmail.Text;
username = textboxUsername.Text;
password = textboxPassword.Text;
//Checking for correct EMAIL
if (!textboxEmail.Text.Contains("#") && (!textboxEmail.Text.Contains(".")))
{
MessageBox.Show("Invalid Email Format");
}
else
{
Account account = new Account(domain, email, username, password);
}
}
WriteAllLines expects an string[] as the second parameter. So you need to create a way to represent a single Account object as a string. The easiest way is to override the ToString method. Then use the Linq Select method to select them.
Also, it would be better if the Account class did not also contain the list of accounts. That should really be a separate class. Try something like this:
void Main()
{
var accountList = new AccountList();
//Save a few accounts to the file
Account a1 = new Account("Google", "GoogleEmail", "GoogleUser", "GooglePass");
accountList.Add(a1);
Account a2 = new Account("Netflix", "NetflixEmail", "NetflixUser", "NetflixPass");
accountList.Add(a2);
AccountList.SaveToFile(#"g:\test\accounts.txt", accountList);
//Load the accounts from the file
AccountList aList2 = AccountList.ReadFromFile(#"g:\test\accounts.txt");
aList2.Dump();
}
public class AccountList
{
private List<Account> accounts;
public IEnumerable<Account> Accounts { get { return accounts;} }
public AccountList()
{
this.accounts = new List<Account>();
}
public void Add(Account a)
{
accounts.Add(a);
}
public static void SaveToFile(string filename, AccountList accounts)
{
//Selects all the `Account` instances and creates a string[]
System.IO.File.WriteAllLines(filename, accounts.Accounts.Select(a => $"{a}").ToArray());
}
public static AccountList ReadFromFile(string filename) // this is meant to be used as authentication in my main form, it isn't necessary right now..
{
var result = new AccountList();
//Read each line from the file and create an Account instance.
foreach (var line in System.IO.File.ReadAllLines(filename))
{
if (!string.IsNullOrWhiteSpace(line))
{
var parts = line.Split(',');
if (parts.Length == 4)
{
Account a = new Account(parts[0], parts[1], parts[2], parts[3]);
result.Add(a);
}
}
}
return result;
}
}
public class Account
{
public string Domain; //this is supposed to be google/skype/facebook
public string Email;
public string Username;
public string Password;
public Account(string domain, string email, string username, string password)
{
Domain = domain;
Email = email;
Username = username;
Password = password;
}
public override string ToString()
{
return $"{Domain},{Email},{Username},{Password}";
}
}
According to your comment, it sounds like you want to append and not write. If you want to append to a file (i.e add to whats already there) you need to use the AppendAllLines() function.
However you have bigger issues because you are trying to write a List of objects, not strings to your file. If you want to just write the passwords, you need this:
private static void SaveToFile()
{
System.IO.File.AppendAllLines("path/to/file", myAccountList.Select(x => x.Password));
}
This method will append to a file if it exists, if it does not exist it just creates a new file.
Documentation here

how to remove duplication from this c# code block

I wrote this code but during code review process it was suggested that this is duplicate code and I need to remove code duplication from this code. Can anyone suggest how I can make this code better to avoid duplication.
private void ShowHideEmailContents(string email, string email2, string format, string tooltip, bool isReadOnly)
{
if (isReadOnly)
{
hlEmail.NavigateUrl = string.Format(format, email);
hlEmail2.NavigateUrl = string.Format(format, email2);
hlEmail.Text = email;
hlEmail2.Text = email2;
hlEmail.ToolTip = tooltip;
hlEmail2.ToolTip = tooltip;
hlEmail.Visible = isReadOnly;
hlEmail2.Visible = isReadOnly;
txtEmail.Visible = !isReadOnly;
txtEmail2.Visible = !isReadOnly;
}
else
{
txtEmail.Text = email;
txtEmail2.Text = email2;
}
}
Note that the duplication exists because you do the same things twice, just on different objects.
To fix that, create a new method which does those things only once:
private static void ShowHideEmailContents(?? hl, ?? txt, string email, string format, string tooltip, bool isReadOnly)
{
if (isReadOnly)
{
hl.NavigateUrl = string.Format(format, email);
hl.Text = email;
...
}
else
{
txt.Text = email;
}
}
and call it twice:
private void ShowHideEmailContents(string email, string email2, string format, string tooltip, bool isReadOnly)
{
ShowHideEmailContents(hlEmail, txtEmail, email, format, tooltip, isReadOnly);
ShowHideEmailContents(hlEmail2, txtEmail2, email2, format, tooltip, isReadOnly);
}
You can minimise the number of parameters that you pass by encapsulating the logic to set the email object's properties in a class:
public sealed class EmailOptionsSetter
{
readonly string _tooltip;
readonly string _format;
readonly bool _isReadOnly;
public EmailOptionsSetter(string tooltip, string format, bool isReadOnly)
{
_tooltip = tooltip;
_format = format;
_isReadOnly = isReadOnly;
}
public void SetOptions(YourEmailType emailObj, string email)
{
emailObj.NavigateUrl = string.Format(_format, email);
emailObj.Text = email;
emailObj.ToolTip = _tooltip;
emailObj.Visible = _isReadOnly;
}
}
Then you can call it like this:
private void ShowHideEmailContents(string email, string email2, string format, string tooltip, bool isReadOnly)
{
if (isReadOnly)
{
var optionsSetter = new EmailOptionsSetter(tooltip, format, isReadOnly);
optionsSetter.SetOptions(hlEmail, email);
optionsSetter.SetOptions(hlEmail2, email2);
txtEmail.Visible = !isReadOnly;
txtEmail2.Visible = !isReadOnly;
}
else
{
txtEmail.Text = email;
txtEmail2.Text = email2;
}
}

WNetAddConnection2 fails but net use succeeds

I am trying to Connect to a network resource using WNetAddConnection2 but its failing with error code ERROR_BAD_NET_NAME (Error Code 67).
But if use "net use" command with the same user name and password its succeeding though.
Any clues ?
public class NETRESOURCE
{
public int dwScope;
public int dwType;
public int dwDisplayType;
public int dwUsage;
public string LocalName;
public string RemoteName;
public string Comment;
public string Provider;
}
[DllImport("mpr.dll")]
public static extern int WNetAddConnection2(NETRESOURCE netResource, string password, string username, int flags);
public class ServerConnect
{
private string serverName;
private string userName;
private string password;
public int nResult;
public ServerConnect()
{
serverName = "";
userName = "";
password = "";
nResult = -1;
}
public void SetConnectionParam(string serName, string uName, string pwd)
{
serverName = serName;
userName = uName;
password = pwd;
}
public void Connect()
{
NETRESOURCE myResource = new NETRESOURCE();
myResource.dwScope = 0;
myResource.dwType = 0x00000001; //RESOURCETYPE_DISK
myResource.dwDisplayType = 0;
myResource.LocalName = "";
myResource.RemoteName = serverName;
myResource.dwUsage = 0;
myResource.Comment = "";
myResource.Provider = "";
nResult = WNetAddConnection2(myResource, password, userName, 0);
}
};
public void ConnectToDataServer(string serverName)
{
ServerConnect oConnect = new ServerConnect();
oConnect.SetConnectionParam(serverName, #"Domain\username", #"password");
Thread connectionThread = new Thread(new ThreadStart(oConnect.Connect));
connectionThread.Start();
while (!connectionThread.IsAlive) ;// Wait till thread starts and Alive
int nCount = 0;
while (connectionThread.IsAlive)
{
Thread.Sleep(500);
nCount++;
if (nCount == 10) // wait for 5 secs
{
//WriteLine(this, "Failed to Connect to to server " + serverName , LogStatus.Error);
connectionThread.Abort();
Thread.Sleep(1000);
}
}
//WriteLine(this, oConnect.nResult.ToString(), LogStatus.Success);
}
public void ConnectToServer()
{
ConnectToDataServer(#"\\ServerName");
}
For one, we would need to see your code, as WNetAddConnection2 is a Windows functions and thus P/Invoked, and P/Invoke operations are always very, very hairy.
On the note of assuming you've invoked correctly, there could be permissions in the way (this is especially true if you're running Windows 8). Try making sure to Run as Administrator when you luanch VS, as this will usually extend the same credentials to executing applications, whereas the console often has different permissions.

Mvc .Net.Mail: How to send email with image (logo)

I am using three classes to send email but i cant to combine text email with image, or just to send image. When i get email i see empty image.
Help me to change my code so i can to send email with:
text
image
and style
public class SendService : IDistributionProvider
{
public int Send(System.Xml.Linq.XDocument recipientsData, string subject, string fromName, string fromAccount)
{
foreach (XElement element in recipientsData.Root.Elements())
{
string email = element.Element("email").Value;
string name = element.Element("name").Value;
string message = element.Element("message").Value;
bool result = EmailUtils.SendEmail(fromAccount, fromName, email, name, subject, message.Replace("\n", "<br/>"));
}
return 1;
}
public interface IDistributionProvider
{
int Send(XDocument recipientsData, string subject, string fromName,
string fromAccount);
}
public static class EmailUtils
{
private static string sendHostName;
private static int sendPort;
private static string userName;
private static string password;
private static string defaultFromEmail;
private static string defaultFromName;
static EmailUtils()
{
sendHostName = ConfigurationManager.AppSettings["sendHostName"];
sendPort = int.Parse(ConfigurationManager.AppSettings["sendPort"]);
defaultFromEmail = ConfigurationManager.AppSettings["fromEmail"];
defaultFromName = ConfigurationManager.AppSettings["fromName"];
string credential = Utils.DecryptString(ConfigurationManager.AppSettings["credential"]);
if (!string.IsNullOrEmpty(credential) && credential.Split(";".ToCharArray()).Length > 1)
{
userName = credential.Split(";".ToCharArray())[0];
password = credential.Split(";".ToCharArray())[1];
}
}
public static bool SendEmail(string toEmail, string toName, string subject, string body)
{
return SendEmail(defaultFromEmail, defaultFromName, toEmail, toName, subject, body);
}
public static bool SendEmail(string fromEmail, string fromName, string toEmail, string toName, string subject, string body)
{
try
{
if (string.IsNullOrEmpty(toEmail))
{
return false;
}
if (string.IsNullOrEmpty(toName))
{
toName = toEmail.Substring(0, toEmail.IndexOf("#"));
}
if (string.IsNullOrEmpty(fromEmail))
{
fromEmail = defaultFromEmail;
}
if (string.IsNullOrEmpty(fromName))
{
fromName = defaultFromName;
}
Message message = new Message();
message.Charset = "UTF-8";
message.Subject = Codec.RFC2047Encode(subject, "UTF-8");
message.From = new Address(fromEmail, fromName);
message.To.Add(toEmail, toName);
message.BodyHtml.Format = BodyFormat.Html;
message.BodyHtml.Charset = "UTF-8";
message.BodyHtml.Text = body;
return ActiveUp.Net.Mail.SmtpClient.SendSsl(message, sendHostName, sendPort, userName, password, SaslMechanism.Login);
}
catch
{
return false;
}
}
}
In this way I send email- just text:
string bodyEmail = "<h2>Welcome to website</h2></br><div><p>Thank for using website</p></div>";
EmailUtils.SendEmail("xxx#gmail.com","xxxx","Contact",bodyEmail);
Easiest way to do it is to inline your images using Data URIs.
You essentially inline the image into the HTML of your message. Just follow the format
data:[<MIME-type>][;charset=<encoding>][;base64]
where mime-type may be image/jpeg, charset should be ASCII, and the bytes of the image converted to base64. You can get that by reading the bytes of the image file from disk
byte[] imaeg = File.ReadAllBytes("nekkedladies.jpg");
then convert the byte array to a base 64 string
var base64Imaeg = System.Convert.ToBase64String(imaeg);
slap it together and stick it in your html (stolen from wiki)
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Nekkid Ladies" />
btw, the example image data isn't nekkid ladies. It's this:
sorry
I've actually ran into this same problem and what really helped me was this. In my case I had the html and I had to parse it out using HtmlUtilityPack. I would not recommend using the encoded string as It is not fully supported, and it makes your message bloated. The cid way is also how outlook adds images to an email. I'd add code but I think the example was good enough in my case.

Categories