Example #1
0
        private async Task OnMessageReceived(object sender, MessageEventArgs e)
        {
            using (Stream stream = e.Message.GetData().Result)
            {
                string to = string.Join(", ", e.Message.Recipients);
                Console.WriteLine($"Message received. Client address {e.Message.Session.ClientAddress}. From {e.Message.From}. To {to}.");
                Message message = new MessageConverter().ConvertAsync(stream, e.Message.From, to).Result;
                message.IsUnread = true;


                await taskQueue.QueueTask(() =>
                {
                    Console.WriteLine("Processing received message");
                    Smtp4devDbContext dbContext = dbContextFactory();

                    Dictionary <MailboxAddress, Exception> relayErrors = TryRelayMessage(message, null);
                    message.RelayError = string.Join("\n", relayErrors.Select(e => e.Key.ToString() + ": " + e.Value.Message));

                    Session dbSession = dbContext.Sessions.Find(activeSessionsToDbId[e.Message.Session]);
                    message.Session   = dbSession;
                    dbContext.Messages.Add(message);

                    dbContext.SaveChanges();

                    TrimMessages(dbContext);
                    dbContext.SaveChanges();
                    notificationsHub.OnMessagesChanged().Wait();
                    Console.WriteLine("Processing received message DONE");
                }, false).ConfigureAwait(false);
            }
        }
Example #2
0
        private async Task OnMessageReceived(object sender, MessageEventArgs e)
        {
            using (Stream stream = e.Message.GetData().Result)
            {
                string to = string.Join(", ", e.Message.Recipients);
                Console.WriteLine($"Message received. Client address {e.Message.Session.ClientAddress}. From {e.Message.From}. To {to}.");
                Message message = new MessageConverter().ConvertAsync(stream, e.Message.From, to).Result;
                message.IsUnread = true;

                await QueueTask(() =>
                {
                    Console.WriteLine("Processing received message");
                    Smtp4devDbContext dbContext = dbContextFactory();

                    Session dbSession = dbContext.Sessions.Find(activeSessionsToDbId[e.Message.Session]);
                    message.Session   = dbSession;
                    dbContext.Messages.Add(message);

                    dbContext.SaveChanges();

                    Smtp4devServer.TrimMessages(dbContext, serverOptions.Value);
                    dbContext.SaveChanges();
                    messagesHub.OnMessagesChanged().Wait();
                    Console.WriteLine("Processing received message DONE");
                }, false).ConfigureAwait(false);
            }
        }
Example #3
0
        private async Task OnMessageReceived(object sender, MessageEventArgs e)
        {
            Message message = new MessageConverter().ConvertAsync(e.Message).Result;

            Console.WriteLine($"Message received. Client address {e.Message.Session.ClientAddress}. From {e.Message.From}. To {message.To}.");
            message.IsUnread = true;


            await taskQueue.QueueTask(() =>
            {
                Console.WriteLine("Processing received message");
                using var scope             = serviceScopeFactory.CreateScope();
                Smtp4devDbContext dbContext = scope.ServiceProvider.GetService <Smtp4devDbContext>();

                Dictionary <MailboxAddress, Exception> relayErrors = TryRelayMessage(message, null);
                message.RelayError = string.Join("\n", relayErrors.Select(e => e.Key.ToString() + ": " + e.Value.Message));

                ImapState imapState = dbContext.ImapState.Single();
                imapState.LastUid   = Math.Max(0, imapState.LastUid + 1);
                message.ImapUid     = imapState.LastUid;

                message.Session = dbContext.Sessions.Find(activeSessionsToDbId[e.Message.Session]);
                dbContext.Messages.Add(message);

                dbContext.SaveChanges();

                TrimMessages(dbContext);
                dbContext.SaveChanges();
                notificationsHub.OnMessagesChanged().Wait();
                Console.WriteLine("Processing received message DONE");
            }, false).ConfigureAwait(false);
        }
Example #4
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory log)
        {
            ServerOptions serverOptions = Configuration.GetSection("ServerOptions").Get <ServerOptions>();


            Action <IApplicationBuilder> configure = subdir => {
                subdir.UseExceptionHandler(new ExceptionHandlerOptions
                {
                    ExceptionHandler = new JsonExceptionMiddleware().Invoke
                });

                subdir.UseDefaultFiles();

                if (env.IsDevelopment())
                {
                    subdir.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
                    {
                        HotModuleReplacement = true
                    });
                }

                subdir.UseStaticFiles();

                subdir.UseWebSockets();
                subdir.UseSignalR(routes =>
                {
                    routes.MapHub <MessagesHub>("/hubs/messages");
                    routes.MapHub <SessionsHub>("/hubs/sessions");
                });

                subdir.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}");

                    routes.MapSpaFallbackRoute(
                        name: "spa-fallback",
                        defaults: new { controller = "Home", action = "Index" });
                });


                Smtp4devDbContext context = subdir.ApplicationServices.GetService <Smtp4devDbContext>();
                if (!context.Database.IsInMemory())
                {
                    context.Database.Migrate();
                }

                subdir.ApplicationServices.GetService <Smtp4devServer>().Start();
            };

            if (!string.IsNullOrEmpty(serverOptions.RootUrl))
            {
                app.Map(serverOptions.RootUrl, configure);
            }
            else
            {
                configure(app);
            }
        }
Example #5
0
        public void Start()
        {
            Smtp4devDbContext dbContent = dbContextFactory();

            foreach (Session unfinishedSession in dbContent.Sessions.Where(s => !s.EndDate.HasValue).ToArray())
            {
                unfinishedSession.EndDate = DateTime.Now;
            }
            dbContent.SaveChanges();

            TrimMessages(dbContent, serverOptions.Value);
            dbContent.SaveChanges();

            TrimSessions(dbContent, serverOptions.Value);
            dbContent.SaveChanges();
            messagesHub.OnMessagesChanged().Wait();
            sessionsHub.OnSessionsChanged().Wait();

            processingQueue         = new BlockingCollection <Action>();
            priorityProcessingQueue = new BlockingCollection <Action>();
            Task.Run(ProcessingTaskWork);

            smtpServer.Start();

            Console.WriteLine($"SMTP Server is listening on port {smtpServer.PortNumber}.\nKeeping last {serverOptions.Value.NumberOfMessagesToKeep} messages and {serverOptions.Value.NumberOfSessionsToKeep} sessions.");
        }
        public void DatesAreStoredInUtcAndKindIsSetOnRetrieval()
        {
            var timeZone = GetTestTimezone();
            var testDate = new DateTime(2021, 1, 4, 10, 0, 0, DateTimeKind.Utc);

            using (new FakeLocalTimeZone(GetTimeZoneInfo(timeZone)))
            {
                using (var context = new Smtp4devDbContext(_sqlLiteForTesting.ContextOptions))
                {
                    context.Messages.Add(new Message {
                        From = "test"
                    });
                    context.SaveChanges();

                    //manually set time so we don't go through any EF converts.
                    var sql = @$ "
UPDATE Messages
SET ReceivedDate = DATETIME('{testDate:yyyy-MM-dd HH:mm:ss}');
";
                    context.Database.ExecuteSqlRaw(sql);
                    context.ChangeTracker.Clear();

                    // verify entity return value
                    var message = context.Messages.Single(x => x.From == "test");
                    message.ReceivedDate.Kind.Should().Be(DateTimeKind.Utc);
                    message.ReceivedDate.ToLocalTime().Should().Be(new DateTime(testDate.Year, testDate.Month, testDate.Day,
                                                                                testDate.Hour + timeZone.Offset, 0, 0, DateTimeKind.Local));
                }
            }
Example #7
0
        private async Task OnSessionCompleted(object sender, SessionEventArgs e)
        {
            int messageCount = (await e.Session.GetMessages()).Count;

            log.Information("Session completed. Client address {clientAddress}. Number of messages {messageCount}.", e.Session.ClientAddress,
                            messageCount);


            await taskQueue.QueueTask(() =>
            {
                using var scope             = serviceScopeFactory.CreateScope();
                Smtp4devDbContext dbContext = scope.ServiceProvider.GetService <Smtp4devDbContext>();

                Session dbSession = dbContext.Sessions.Find(activeSessionsToDbId[e.Session]);
                UpdateDbSession(e.Session, dbSession).Wait();
                dbContext.SaveChanges();

                TrimSessions(dbContext);
                dbContext.SaveChanges();

                activeSessionsToDbId.Remove(e.Session);

                notificationsHub.OnSessionsChanged().Wait();
            }, false).ConfigureAwait(false);
        }
Example #8
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory log)
        {
            ServerOptions serverOptions = Configuration.GetSection("ServerOptions").Get <ServerOptions>();

            app.UseRouting();


            Action <IApplicationBuilder> configure = subdir =>
            {
                subdir.UseDeveloperExceptionPage();
                subdir.UseDefaultFiles();
                subdir.UseStaticFiles();
                subdir.UseSpaStaticFiles();

                subdir.UseWebSockets();

                subdir.UseEndpoints(e =>
                {
                    e.MapHub <MessagesHub>("/hubs/messages");
                    e.MapHub <SessionsHub>("/hubs/sessions");

                    e.MapControllers();
                    if (env.IsDevelopment())
                    {
                        e.MapToVueCliProxy(
                            "{*path}",
                            new SpaOptions {
                            SourcePath = "ClientApp"
                        },
                            npmScript: "serve",
                            regex: "Compiled successfully",
                            forceKill: true
                            );
                    }
                });



                Smtp4devDbContext context = subdir.ApplicationServices.GetService <Smtp4devDbContext>();
                if (!context.Database.IsInMemory())
                {
                    context.Database.Migrate();
                }

                subdir.ApplicationServices.GetService <Smtp4devServer>().Start();
            };

            if (!string.IsNullOrEmpty(serverOptions.RootUrl))
            {
                app.Map(serverOptions.RootUrl, configure);
            }
            else
            {
                configure(app);
            }
        }
Example #9
0
 internal Task DeleteMessage(Guid id)
 {
     return(QueueTask(async() =>
     {
         Smtp4devDbContext dbContext = dbContextFactory();
         dbContext.Messages.RemoveRange(dbContext.Messages.Where(m => m.Id == id));
         await dbContext.SaveChangesAsync();
         await messagesHub.OnMessagesChanged();
     }, true));
 }
Example #10
0
 internal Task DeleteAllMessages()
 {
     return(QueueTask(async() =>
     {
         Smtp4devDbContext dbContext = dbContextFactory();
         dbContext.Messages.RemoveRange(dbContext.Messages);
         await dbContext.SaveChangesAsync();
         await messagesHub.OnMessagesChanged();
     }, true));
 }
Example #11
0
 internal Task DeleteAllSessions()
 {
     return(QueueTask(() =>
     {
         Smtp4devDbContext dbContext = dbContextFactory();
         dbContext.Sessions.RemoveRange(dbContext.Sessions.Where(s => s.EndDate.HasValue));
         dbContext.SaveChanges();
         sessionsHub.OnSessionsChanged().Wait();
     }, true));
 }
Example #12
0
 public Task DeleteAllMessages()
 {
     return(QueueTask(() =>
     {
         Smtp4devDbContext dbContext = dbContextFactory();
         dbContext.Messages.RemoveRange(dbContext.Messages);
         dbContext.SaveChanges();
         messagesHub.OnMessagesChanged().Wait();
     }, true));
 }
Example #13
0
 public Task DeleteMessage(Guid id)
 {
     return(QueueTask(() =>
     {
         Smtp4devDbContext dbContext = dbContextFactory();
         dbContext.Messages.RemoveRange(dbContext.Messages.Where(m => m.Id == id));
         dbContext.SaveChanges();
         messagesHub.OnMessagesChanged().Wait();
     }, true));
 }
Example #14
0
 public Task DeleteAllSessions()
 {
     return(taskQueue.QueueTask(() =>
     {
         using var scope = serviceScopeFactory.CreateScope();
         Smtp4devDbContext dbContext = scope.ServiceProvider.GetService <Smtp4devDbContext>();
         dbContext.Sessions.RemoveRange(dbContext.Sessions.Where(s => s.EndDate.HasValue));
         dbContext.SaveChanges();
         notificationsHub.OnSessionsChanged().Wait();
     }, true));
 }
Example #15
0
 public SqliteInMemory()
 {
     this.ContextOptions = new DbContextOptionsBuilder <Smtp4devDbContext>()
                           .UseSqlite(CreateInMemoryDatabase())
                           .Options;
     _connection       = RelationalOptionsExtension.Extract(ContextOptions).Connection;
     using var context = new Smtp4devDbContext(ContextOptions);
     context.Database.EnsureDeleted();
     context.Database.EnsureCreated();
     context.SaveChanges();
 }
Example #16
0
        internal Task DeleteSession(Guid id)
        {
            return(QueueTask(async() =>
            {
                Smtp4devDbContext dbContext = dbContextFactory();
                dbContext.Sessions.RemoveRange(dbContext.Sessions.Where(s => s.Id == id));

                dbContext.SaveChanges();

                await sessionsHub.OnSessionsChanged();
            }, true));
        }
Example #17
0
        private async void OnMessageReceived(object sender, MessageEventArgs e)
        {
            Smtp4devDbContext dbContent = dbContextFactory();

            using (Stream stream = e.Message.GetData())
            {
                Message message = await new MessageConverter().ConvertAsync(stream, e.Message.From, string.Join(", ", e.Message.To));
                dbContent.Messages.Add(message);
            }

            dbContent.SaveChanges();
            messagesHub.OnMessagesChanged().Wait();
        }
Example #18
0
        public MessagesControllerTests()
        {
            messagesRepository = Substitute.For <IMessagesRepository>();
            server             = Substitute.For <ISmtp4devServer>();
            controller         = new MessagesController(messagesRepository, server);
            var sqlLiteForTesting = new SqliteInMemory();

            context = new Smtp4devDbContext(sqlLiteForTesting.ContextOptions);
            InitRepo();
            messagesRepository.GetMessages(Arg.Any <bool>())
            .Returns(context.Messages);
            messagesRepository.DbContext.Returns(context);
        }
Example #19
0
        private void OnMessageReceived(object sender, MessageEventArgs e)
        {
            Smtp4devDbContext dbContent = dbContextFactory();

            using (Stream stream = e.Message.GetData())
            {
                Message message = new MessageConverter().Convert(stream);
                dbContent.Messages.Add(message);
            }

            dbContent.SaveChanges();
            messagesHub.OnMessagesChanged().Wait();
        }
Example #20
0
        private void OnSessionStarted(object sender, SessionEventArgs e)
        {
            Console.WriteLine($"Session started. Client address {e.Session.ClientAddress}");
            Smtp4devDbContext dbContent = dbContextFactory();

            Session session = new Session();

            UpdateDbSession(e, session);
            dbContent.Sessions.Add(session);
            dbContent.SaveChanges();

            sessionToDbId[e.Session] = session.Id;
        }
Example #21
0
        internal Task MarkMessageRead(Guid id)
        {
            return(QueueTask(async() => {
                Smtp4devDbContext dbContent = dbContextFactory();
                DbModel.Message message = await dbContent.Messages.FindAsync(id);

                if (message.IsUnread)
                {
                    message.IsUnread = false;
                    dbContent.SaveChanges();
                    await messagesHub.OnMessagesChanged();
                }
            }, true));
        }
Example #22
0
        public Task MarkMessageRead(Guid id)
        {
            return(QueueTask(() => {
                Smtp4devDbContext dbContent = dbContextFactory();
                DbModel.Message message = dbContent.Messages.FindAsync(id).Result;

                if (message.IsUnread)
                {
                    message.IsUnread = false;
                    dbContent.SaveChanges();
                    messagesHub.OnMessagesChanged().Wait();
                }
            }, true));
        }
Example #23
0
        private async Task OnSessionStarted(object sender, SessionEventArgs e)
        {
            Console.WriteLine($"Session started. Client address {e.Session.ClientAddress}.");
            await QueueTask(async() => {
                Smtp4devDbContext dbContent = dbContextFactory();

                Session dbSession = new Session();
                await UpdateDbSession(e.Session, dbSession);
                dbContent.Sessions.Add(dbSession);
                dbContent.SaveChanges();

                sessionToDbId[e.Session] = dbSession.Id;
            }, false);
        }
Example #24
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory log)
        {
            app.UseExceptionHandler(new ExceptionHandlerOptions
            {
                ExceptionHandler = new JsonExceptionMiddleware().Invoke
            });

            app.UseDefaultFiles();


            bool webpackConfigPresent = File.Exists(Path.Combine(env.ContentRootPath, "webpack.config.js"));

            if (env.IsDevelopment() && webpackConfigPresent)
            {
                app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
                {
                    HotModuleReplacement = true
                });
            }

            app.UseStaticFiles();

            app.UseWebSockets();
            app.UseSignalR(routes =>
            {
                routes.MapHub <MessagesHub>("/hubs/messages");
                routes.MapHub <SessionsHub>("/hubs/sessions");
            });

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Home", action = "Index" });
            });


            Smtp4devDbContext context = app.ApplicationServices.GetService <Smtp4devDbContext>();

            if (!context.Database.IsInMemory())
            {
                context.Database.Migrate();
            }

            app.ApplicationServices.GetService <Smtp4devServer>().Start();
        }
Example #25
0
 public Task DeleteSession(Guid id)
 {
     return(taskQueue.QueueTask(() =>
     {
         using var scope = serviceScopeFactory.CreateScope();
         Smtp4devDbContext dbContext = scope.ServiceProvider.GetService <Smtp4devDbContext>();
         Session session = dbContext.Sessions.SingleOrDefault(s => s.Id == id);
         if (session != null)
         {
             dbContext.Sessions.Remove(session);
             dbContext.SaveChanges();
             notificationsHub.OnSessionsChanged().Wait();
         }
     }, true));
 }
Example #26
0
        internal Task DeleteSession(Guid id)
        {
            return(QueueTask(() =>
            {
                Smtp4devDbContext dbContext = dbContextFactory();

                Session session = dbContext.Sessions.FirstOrDefault(s => s.Id == id);
                if (session != null)
                {
                    dbContext.Sessions.Remove(session);
                    dbContext.SaveChanges();
                    sessionsHub.OnSessionsChanged().Wait();
                }
            }, true));
        }
Example #27
0
        private void OnSessionCompleted(object sender, SessionEventArgs e)
        {
            Console.WriteLine($"Session completed. Client address {e.Session.ClientAddress}. Number of messages {e.Session.GetMessages().Length}");
            Smtp4devDbContext dbContent = dbContextFactory();

            Session session = dbContent.Sessions.Find(sessionToDbId[e.Session]);

            UpdateDbSession(e, session);
            dbContent.SaveChanges();

            TrimSessions(dbContent);
            dbContent.SaveChanges();


            sessionsHub.OnSessionsChanged().Wait();
        }
Example #28
0
        private async Task OnSessionStarted(object sender, SessionEventArgs e)
        {
            log.Information("Session started. Client address {clientAddress}.", e.Session.ClientAddress);
            await taskQueue.QueueTask(() =>
            {
                using var scope             = serviceScopeFactory.CreateScope();
                Smtp4devDbContext dbContext = scope.ServiceProvider.GetService <Smtp4devDbContext>();

                Session dbSession = new Session();
                UpdateDbSession(e.Session, dbSession).Wait();
                dbContext.Sessions.Add(dbSession);
                dbContext.SaveChanges();

                activeSessionsToDbId[e.Session] = dbSession.Id;
            }, false).ConfigureAwait(false);
        }
Example #29
0
        private void OnSessionCompleted(object sender, SessionEventArgs e)
        {
            Smtp4devDbContext dbContent = dbContextFactory();

            Session session = new Session();

            session.EndDate          = e.Session.EndDate.GetValueOrDefault(DateTime.Now);
            session.ClientAddress    = e.Session.ClientAddress.ToString();
            session.ClientName       = e.Session.ClientName;
            session.NumberOfMessages = e.Session.GetMessages().Length;
            session.Log = e.Session.GetLog().ReadToEnd();
            dbContent.Sessions.Add(session);

            dbContent.SaveChanges();

            sessionsHub.OnSessionsChanged().Wait();
        }
Example #30
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseExceptionHandler(new ExceptionHandlerOptions
            {
                ExceptionHandler = new JsonExceptionMiddleware().Invoke
            });

            app.UseDefaultFiles();
            app.UseStaticFiles();

            app.UseMvc();

            app.UseWebSockets();
            app.UseSignalR(routes =>
            {
                routes.MapHub <MessagesHub>("hubs/messages");
                routes.MapHub <SessionsHub>("hubs/sessions");
            });



            app.ApplicationServices.GetService <Smtp4devServer>().Start();

            if (env.IsDevelopment())
            {
                Smtp4devDbContext db = app.ApplicationServices.GetService <Smtp4devDbContext>();

                MessageConverter messageConverter = new MessageConverter();


                using (Stream stream = File.OpenRead("example.eml"))
                {
                    Message message = messageConverter.Convert(stream);
                    db.Messages.Add(message);
                }

                using (Stream stream = File.OpenRead("example2.eml"))
                {
                    Message message = messageConverter.Convert(stream);
                    db.Messages.Add(message);
                }

                db.SaveChanges();
            }
        }