Failure to trigger message when e-mails are sent asynchronously - c#

I have a method that sends e-mails (using FluentEmail), and I want to trigger a message when they're sent.
They are sent asynchronously.
This is my method:
using System.Net;
using System.Net.Mail;
using FluentEmail.Core;
using FluentEmail.Smtp;
public void SendEmail() {
try {
var sender = new SmtpSender(() => new SmtpClient(host: "smtp.office365.com") {
EnableSsl = true,
UseDefaultCredentials = false,
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = new NetworkCredential("my#email.com", "myPassword"),
Port = 587
});
Email.DefaultSender = sender;
var newEmail = Email
.From("my#email.com")
.To("their#email.com")
.Subject("a thousand blessings upon you")
.Body("receive these blessings");
foreach (var company in groupedByCompany) {
string o = company.Select(x => x.PropertyName).FirstOrDefault().ToString();
string n = company.Select(x => x.ProperyNameTwo).FirstOrDefault().ToString();
newEmail.AttachFromFilename($#"C:\filepath\{o + n}", "application/pdf", "this is the preview text");
var result = newEmail.SendAsync();
if (result.IsCompleted == true) { //this is System.Threading.Tasks.Task<FluentEmail.Core.Models.SendResponse> result
Console.WriteLine("E-mail sent!");
} else {
Console.WriteLine("Could not send e-mail.");
}
} catch (Exception ex) {
// handle exception
}
}
But the e-mail is sent without any messages in Output.
I see that IsCompleted will be true if one of three conditions are met:
TaskStatus.RanToCompletion
TaskStatus.Faulted
TaskStatus.Canceled
What could I use instead of IsCompleted / what am I doing wrong?

Related

Image not displayed in Outlook in ASP

After sending an email the logo is not displayed in Outlook but it works in Gmail.
I found that in the inspect element that the image src is changed into blockedimagesrc
In my Controller :
var NotifyCompany = new NotifyCompany()
{
Email = model.regE,
EmailTo = contact.GetPropertyValue<string>("email"),
DateRegistered = DateTime.UtcNow
};
EmailHelpers.SendEmail(NotifyCompany, "NotifyCompany", "New Client Registered");
Helpers :
public static ActionResponse SendEmail(IEmail model, string emailTemplate, string subject, List<HttpPostedFileBase> files = null)
{
try
{
var template =
System.IO.File.ReadAllText(HttpContext.Current.Server.MapPath(string.Format("~/Templates/{0}.cshtml", emailTemplate)));
var body = Razor.Parse(template, model);
var attachments = new List<Attachment>();
if (files != null && files.Any())
{
foreach (var file in files)
{
var att = new Attachment(file.InputStream, file.FileName);
attachments.Add(att);
}
}
var email = Email
.From(ConfigurationManager.AppSettings["Email:From"], "myWebsiteEmail")
.To(model.EmailTo)
.Subject(subject)
.Attach(attachments)
.Body(body).BodyAsHtml();
email.Send();
return new ActionResponse()
{
Success = true
};
}
catch (Exception ex)
{
return new ActionResponse()
{
Success = false,
ErrorMessage = ex.Message
};
}
}
In my Email Template :
<img src="/mysite.com/image/logo.png"/>
Any help would be appreciated.
Outlook web access will block any images by default - only if the user chooses to display/download images these will be displayed/downloaded. I am not sure if it is possible to adjust the default behavior by using office 365 admincenter or the OWA settings.
Some time ago it was possible to work around this by using it as a background image inside a table>tr>td cell background-image css property.
EDIT
Checked a recent project of myself, where we are sending notification mails about tickets. The site logo is displayed correctly in outlook/owa - without adding the recipient to the trusted list:
using (MailMessage mm = new MailMessage(sender, header.RecipientAddress, header.Subject, header.Body))
{
mm.Body = header.Body;
mm.BodyEncoding = Encoding.UTF8;
mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
mm.Priority = priority == IntMailPriority.High ? MailPriority.High : MailPriority.Normal;
mm.IsBodyHtml = bodyIsHtml;
// logo
if (bodyIsHtml)
{
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(header.Body, Encoding.UTF8, "text/html");
string logoPath = $"{AppDomain.CurrentDomain.BaseDirectory}\\images\\logo_XXX.png";
LinkedResource siteLogo = new LinkedResource(logoPath)
{
ContentId = "logoId"
};
htmlView.LinkedResources.Add(siteLogo);
mm.AlternateViews.Add(htmlView);
}
// create smtpclient
SmtpClient smtpClient = new SmtpClient(smtpSettings.ServerAddress, smtpSettings.Port)
{
Timeout = 30000,
DeliveryMethod = SmtpDeliveryMethod.Network
};
// set relevant smtpclient settings
if (smtpSettings.UseTlsSsl)
{
smtpClient.EnableSsl = true;
// needed for invalid certificates
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
}
if (smtpSettings.UseAuth)
{
smtpClient.UseDefaultCredentials = false;
NetworkCredential smtpAuth = new NetworkCredential { UserName = smtpSettings.Username, Password = smtpSettings.Password };
smtpClient.Credentials = smtpAuth;
}
smtpClient.Timeout = smtpSettings.SendingTimeout * 1000;
// finally sent mail \o/ :)
try
{
smtpClient.Send(mm);
}
catch (SmtpException exc)
{
throw new ProgramException(exc, exc.Message);
}
catch (InvalidOperationException exc)
{
throw new ProgramException(exc, exc.Message);
}
catch (AuthenticationException exc)
{
throw new ProgramException(exc, exc.Message);
}
}
Afterwards the logo is referred to as
<IMG alt="Intex Logo" src="cid:logoId">
inside the generated html.

RabbitMq sending message twice to the same consumer

I have implemented a rabbitmq messaging in my application. A very weird behaviour then.
My publisher is a webservice, while my consumer is a console application. After recieving the message I ack it immediately and span a new thread to process which take like 2 seconds to finish.
But the same message is sent with the previous delivery tag incremented by one. I am using topic based routing.
What would I be doing wrong?
Subscriber:
//Create the connection factory
var connectionFactory = new ConnectionFactory()
{
HostName = host,
UserName = userName,
Password = password
};
connectionFactory.RequestedHeartbeat = 10;
connectionFactory.RequestedConnectionTimeout = 30000;
connectionFactory.AutomaticRecoveryEnabled = true;
connectionFactory.NetworkRecoveryInterval = TimeSpan.FromSeconds(10);
//connection
var connection = connectionFactory.CreateConnection();
logger.Info($"Connected to RabbitMQ {host}");
connection.ConnectionShutdown += Connection_ConnectionShutdown;
var model = connection.CreateModel();
model.BasicQos(0, 1, false);
var consumer = new QueueingBasicConsumer(model);
model.BasicConsume(queueName, false, consumer);
while (true)
{
try
{
var deliveryArgs = consumer.Queue.Dequeue();
model.BasicAck(deliveryArgs.DeliveryTag, false);
var jsonString = Encoding.Default.GetString(deliveryArgs.Body);
var itemtoprocess = jsonString.FromJson < recieved message > ();
if (deliveryArgs.Redelivered)
{
model.BasicReject(deliveryArgs.DeliveryTag, false);
}
else
{
var task = Task.Factory.StartNew(() => {
//Do work here on different thread then this one
//Call the churner to process the message
//Some long running method here to process item recieve
});
Task.WaitAll(task);
}
}
catch (EndOfStreamException ex)
{
//log
}
}
Setup:
public void Init(string exchangeName, string queueName, string routingKey = "")
{
using (IConnection connection = connectionFactory.CreateConnection())
{
using (IModel channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchangeName, ExchangeType.Topic, true, false, null);
//Queue
var queue = channel.QueueDeclare(queueName, true, false, false, null);
channel.QueueBind(queue.QueueName, exchangeName, routingKey);
}
}
}

Why am I getting "The specified string is not in the form required for an e-mail address" here?

The relevant code is
[HttpPost]
public ActionResult GetLinkByName ( string pname )
{
PartnerIdAndEmail PInfo = this._Db.GetPartnerByName(pname);
if ( PInfo != null )
{
try
{
var m = new System.Net.Mail.MailMessage()
{
Subject = "Your Survey Link",
Body = String.Format("<p>Your survey link is {0}</p>",
String.Format("{0}Answers/FillOut?pid={1}",this.GetBaseUrl(),PInfo.Id)),
IsBodyHtml = true
};
m.From = new MailAddress("admin#mycompany.com", "Administrator"); // placeholder of the address I'm sending the email from
m.To.Add(PInfo.Email);
SmtpClient smtp = new SmtpClient
{
Host = "something#somethingelse.net", // this is a placeholder of the value of "SMTP Server" in my IIS
Port = 25, // this is the value of "Port" in my IIS
Credentials = null,
EnableSsl = false
};
smtp.Send(m);
} catch (Exception e) { return Json(new { succeeded = false, msg = e.Message }); }
// If here, we can assume the message was successfully sent
return Json(new { succeeded = true, msg = "Thanks! You should receive an email with your survey link soon." });
}
else
{
return Json(new {
succeeded = false,
msg = String.Format("Oops! There was a problem in finding the info for partner {0}", pname)
});
}
}
and I can't figure out the exact line since it's a run-time error. I've verified that PInfo.Email when I run the program is a valid email address. So I don't know what could be the problem here. Any ideas? Or any suggestions for how I can debug this?

Message deleted automatically RabbitMQ

I have used RabbitMQ for storing messages. I noticed that messages are deleted when application restart.
I have producer and consumer in same application.
Please find producer and consumer as below. I have used durable queue as well as durable message.
So if there is only one consumer of queue and it's not consume currently then queue messages are deleted. Is it so ?
Producer:
public static void PublishMessage(RequestDto message, string queueName)
{
var factory = new ConnectionFactory() { HostName = Config.RabbitMqHostName, Port = Config.RabbitMqPortNumber };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queueName, true, false, false, null);
var properties = channel.CreateBasicProperties();
properties.SetPersistent(true);
// properties.DeliveryMode = 2; I have used this too.
string serializesMessage = Utility.SerializeSoapObject(message);
var messageBytes = Encoding.UTF8.GetBytes(serializesMessage);
channel.BasicPublish("", queueName, properties , messageBytes);
Log.Info("Record added into queue : \nMessage: " + serializesMessage);
}
}
}
Consumer:
var factory = new ConnectionFactory() { HostName = Config.RabbitMqHostName, Port = Config.RabbitMqPortNumber };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(Config.RabbitMqQueueName, true, false, false, null);
var consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume(Config.RabbitMqQueueName, true, consumer);
while (DoProcessMessage())
{
try
{
List<RequestDto> messages = GetMessagesInBatch(consumer);
if (messages.Count > 0)
{
ProcessMessageInParallel(messages);
}
else
{
Producer.FillRequestMessages();
}
}
catch (Exception exception)
{
Log.Error("StartConsumer - Failed to process message from RabbitMq Error: " + exception.Message, exception);
}
}
}
}
}
catch (Exception exception)
{
Log.Error(exception.Message, exception);
}
private bool DoProcessMessage()
{
return Config.MaxRequestPerDayCount > 1000;
}
If anyone can help.
You seem to be passing noAck = true to the basicConsume function:
https://www.rabbitmq.com/releases/rabbitmq-java-client/v1.7.0/rabbitmq-java-client-javadoc-1.7.0/com/rabbitmq/client/Channel.html#basicConsume(java.lang.String, boolean, com.rabbitmq.client.Consumer)
In no ack mode, RabbitMQ will send the messages to the consumer and immediately delete it from the queue.

RabbitMq Implementation Practically

I am working on rabbitmq and I am confused with some points Like.
I have just implemented a sample from internet which creates a queue and then it fetch
the message from that queue thereby showing it on the webpage.
Now my problem is::
Suppose My server has RabbitmQ installed and multiple users are accessing this website where I
have implemented the rabbitmq.Now, first user sends a message but to whome it will send this message?
To all the users who will open the page because the code will be common for sent message and the name
of the queue will also be same.
Suppose, first user send one message="Hello" on the queue "Queue1"
now, one other user sends another message="Hello World" on the same queue
and one more user sends a message="Hello Worl World" on the same queue.
Now nth user clicks on receive message then which message will be shown to him?
first ,second or third one?
It means we will always have a single queue for my application?
Can somebody please guide me. I am pretty much confused...
Below I am pasting the code sample I will be using for my website
//For sending the messge
protected void btnSendMail_Click(object sender, EventArgs e)
{
try
{
var factory = new ConnectionFactory();
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
// ConnectionFactory factory = new ConnectionFactory() { HostName = "localhost" };
// // factory.UserName = txtUserEmail.Text.ToString();
//// factory.Password = "password";
// factory.VirtualHost = "/";
// factory.Protocol = Protocols.FromEnvironment();
// factory.HostName = "localhost";
// factory.Port = AmqpTcpEndpoint.UseDefaultPort;
// IConnection conn = factory.CreateConnection();
// using (var channel = conn.CreateModel())
// {
// channel.QueueDeclare("hello", false, false, false, null);
// string message = "Hello World!";
// var body = Encoding.UTF8.GetBytes(txtUserEmail.Text.ToString());
// channel.BasicPublish("", "hello", null, body);
// conn.Close();
// }
//Sending Message
channel.QueueDeclare("hello1", false, false, false, null);
string message = txtUserEmail.Text.ToString();
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish("", "hello1", null, body);
//Console.WriteLine(" [x] Sent {0}", message);
//Console.ReadLine();
Label1.Text = Encoding.Default.GetString(body);
}
}
}
catch
{
}
}
//For receiving the message.
protected void btnReceive_Click(object sender, EventArgs e)
{
try
{
//var factory = new ConnectionFactory() { HostName = "localhost" };
//using (var connection = factory.CreateConnection())
//{
// using (var channel = connection.CreateModel())
// {
// channel.QueueDeclare("hello", false, false, false, null);
// BasicGetResult result = channel.BasicGet("hello", false);
// var consumer = new QueueingBasicConsumer(channel);
// channel.BasicConsume("hello", true, consumer);
// Console.WriteLine(" [*] Waiting for messages." +
// "To exit press CTRL+C");
// while (true)
// {
// var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
// var body = ea.Body;
// var message = Encoding.UTF8.GetString(body);
// Console.WriteLine(" [x] Received {0}", message);
// Label1.Text = message.ToString();
// }
// }
//}
var factory = new ConnectionFactory();
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
bool noAck = false;
BasicGetResult result = channel.BasicGet("hello1", noAck);
if (result == null)
{
}
else
{
IBasicProperties props = result.BasicProperties;
byte[] Body = result.Body;
Label1.Text = Encoding.Default.GetString(Body);
}
}
}
}
catch
{
}
}
If you are creating a messaging system using RabbitMQ you should probably publish your messages to an exchange and then attach a queue to the exchange for each user of the site. Then have the exchange route the messages to the right user/users queue.
You need a better understanding of messaging patterns associated with the use of RabbitMQ
These tutorials would be most relevant
Publish/Subscribe
http://www.rabbitmq.com/tutorials/tutorial-three-python.html
Routing
http://www.rabbitmq.com/tutorials/tutorial-four-python.html
The tutorials are also available in c# if you need it.

Categories