public async Task <bool> SendMail(EmailRequestDto emailDto) { var message = new MimeMessage { Subject = emailDto.Subject, }; /* * if (emailDto.From != _config.Smtp.Username) * return false; */ // ignore from email right now! // TODO: may we need to handle the from email later message.From.Add(MailboxAddress.Parse(_config.Smtp.Username)); foreach (string to in emailDto.To) { message.To.Add(MailboxAddress.Parse(to)); } if (emailDto.CC != null) { foreach (string cc in emailDto.CC) { message.Cc.Add(MailboxAddress.Parse(cc)); } } if (emailDto.BCC != null) { foreach (string bcc in emailDto.BCC) { message.Bcc.Add(MailboxAddress.Parse(bcc)); } } BodyBuilder MailBodyBuilder = new () { TextBody = emailDto.Body }; // Add Attachments List <string> Attachments = new(); if (emailDto.Attachments != null) { Random rand = new(); foreach (string attachmentDataURL in emailDto.Attachments) { string FileName = _helper.Base64ToFile(attachmentDataURL, rand); MailBodyBuilder.Attachments.Add(FileName); Attachments.Add(FileName); } } message.Body = MailBodyBuilder.ToMessageBody(); // SMTP Setup using (var client = new SmtpClient()) { client.ServerCertificateValidationCallback = (s, c, h, e) => true; await client.ConnectAsync(_config.Smtp.Host, _config.Smtp.Port, SecureSocketOptions.StartTls); await client.AuthenticateAsync(_config.Smtp.Username, _config.Smtp.Password); await client.SendAsync(message); await client.DisconnectAsync(true); } _helper.RemoveTempFiles(Attachments); return(true); } }
public void Listen() { var factory = new ConnectionFactory { Uri = new Uri($"amqp://{_config.MassTransit.Username}:{_config.MassTransit.Password}@{_config.MassTransit.Host}:{_config.MassTransit.Port}"), AutomaticRecoveryEnabled = true, NetworkRecoveryInterval = TimeSpan.FromSeconds(_config.MassTransit.NetworkRecoveryIntervalSeconds) }; using IConnection connection = factory.CreateConnection(); using IModel channel = connection.CreateModel(); // Consume 2 by 2 messages channel.BasicQos(0, 2, false); EventingBasicConsumer consumer = new(channel); consumer.Received += async(sender, ea) => { try { #region check retries if (ea.BasicProperties.Headers != null) { ea.BasicProperties.Headers.TryGetValue("x-delivery-count", out object deliveryCountObj); int deliveryCount = Convert.ToInt32(deliveryCountObj); if (deliveryCount > _config.MaxMessageRetries) { // Save in database in case you need to requeue string emailRequestMessage = Encoding.UTF8.GetString(ea.Body.ToArray()); Message messageRequest = JsonConvert.DeserializeObject <Message>(emailRequestMessage); using (var scope = _provider.CreateScope()) { var _context = scope.ServiceProvider.GetService <DataContext>(); try { // add the stuck email request messageRequest.Status = MessageStatuses.ERROR; messageRequest.UpdatedAt = DateTime.Now; _context.Messages.Update(messageRequest); await _context.SaveChangesAsync(); Console.WriteLine("message is stuck, notification send to database"); } catch (Exception) { // Record may be delete _context.Entry(messageRequest).State = EntityState.Detached; await _context.Messages.AddAsync(messageRequest); await _context.SaveChangesAsync(); Console.WriteLine("record removed from database, a new record created"); } } // remove from queue channel.BasicReject(ea.DeliveryTag, false); throw new Exception(message: "message is stuck, removed from queue"); } } #endregion string message = Encoding.UTF8.GetString(ea.Body.ToArray()); Message messageRequestDone = JsonConvert.DeserializeObject <Message>(message); EmailRequestDto emailRequestDto = JsonConvert.DeserializeObject <EmailRequestDto>(messageRequestDone.Body); using (var scope = _provider.CreateScope()) { var _context = scope.ServiceProvider.GetService <DataContext>(); try { bool messageSent = await _mailService.SendMail(emailRequestDto); if (messageSent) { Console.WriteLine("Mail Sent!"); channel.BasicAck(ea.DeliveryTag, false); _context.Messages.Remove(messageRequestDone); await _context.SaveChangesAsync(); Console.WriteLine("message status updated to proceed"); } else { // requeue channel.BasicNack(ea.DeliveryTag, false, true); } } catch (Exception ex) { // log sending error MessageErrorLog messageErrorLog = messageRequestDone.PrepareMessageError(ex.Message); await _context.MessagesErrorLogs.AddAsync(messageErrorLog); await _context.SaveChangesAsync(); } } } catch (Exception ex) { Console.WriteLine($"error: {ex.Message} /n"); } }; channel.BasicConsume(_config.MassTransit.Queue, false, consumer); Console.ReadLine(); }