Example #1
0
        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);
        }
    }
Example #2
0
        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();
        }