Skip to content

Commit 0ad6265

Browse files
authored
Merge pull request #345 from ChangemakerStudios/feature/ServiceTrayNotification
Add Papercut SMTP Service Tray Manager
2 parents a49f34e + f6be99a commit 0ad6265

File tree

69 files changed

+2412
-587
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2412
-587
lines changed

Papercut.sln

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 17
4-
VisualStudioVersion = 17.9.34701.34
3+
# Visual Studio Version 18
4+
VisualStudioVersion = 18.0.11205.157
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Papercut", "src\Papercut.UI\Papercut.csproj", "{AC067042-66BD-4110-ADA1-E2CEA43E7947}"
77
EndProject
@@ -57,6 +57,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Papercut.Infrastructure.Smt
5757
EndProject
5858
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
5959
ProjectSection(SolutionItems) = preProject
60+
examples\appsettings.json = examples\appsettings.json
6061
examples\Directory.Build.props = examples\Directory.Build.props
6162
examples\README.md = examples\README.md
6263
EndProjectSection
@@ -75,6 +76,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SendRichEmailTest", "exampl
7576
EndProject
7677
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SendWordWrapTest", "examples\SendWordWrapTest\SendWordWrapTest.csproj", "{EA8024E3-5D17-3271-8D7A-BC8982C05ADE}"
7778
EndProject
79+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Papercut.Service.TrayNotification", "src\Papercut.Service.TrayNotification\Papercut.Service.TrayNotification.csproj", "{83838EEA-4004-B056-5AA6-4BB789F67A07}"
80+
EndProject
7881
Global
7982
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8083
Debug|AnyCPU = Debug|AnyCPU
@@ -313,6 +316,18 @@ Global
313316
{EA8024E3-5D17-3271-8D7A-BC8982C05ADE}.Release|x64.Build.0 = Release|Any CPU
314317
{EA8024E3-5D17-3271-8D7A-BC8982C05ADE}.Release|x86.ActiveCfg = Release|Any CPU
315318
{EA8024E3-5D17-3271-8D7A-BC8982C05ADE}.Release|x86.Build.0 = Release|Any CPU
319+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
320+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Debug|AnyCPU.Build.0 = Debug|Any CPU
321+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Debug|x64.ActiveCfg = Debug|x64
322+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Debug|x64.Build.0 = Debug|x64
323+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Debug|x86.ActiveCfg = Debug|x86
324+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Debug|x86.Build.0 = Debug|x86
325+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Release|AnyCPU.ActiveCfg = Release|Any CPU
326+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Release|AnyCPU.Build.0 = Release|Any CPU
327+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Release|x64.ActiveCfg = Release|x64
328+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Release|x64.Build.0 = Release|x64
329+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Release|x86.ActiveCfg = Release|x86
330+
{83838EEA-4004-B056-5AA6-4BB789F67A07}.Release|x86.Build.0 = Release|x86
316331
EndGlobalSection
317332
GlobalSection(SolutionProperties) = preSolution
318333
HideSolutionNode = FALSE

src/Papercut.Core/Domain/Message/MessageEntry.cs

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,38 +39,14 @@ public class MessageEntry : INotifyPropertyChanged, IEquatable<MessageEntry>, IF
3939

4040
protected DateTime? _created;
4141

42-
private bool _hasBeenSeen;
42+
protected bool _hasBeenSeen;
4343

44-
private bool _isSelected;
44+
protected bool _isSelected;
4545

4646
public MessageEntry(FileInfo fileInfo)
4747
{
4848
_info = fileInfo;
49-
50-
var firstBit = _info.Name.Split(' ').FirstOrDefault();
51-
52-
if (firstBit?.Length == DateTimeFormat.Length)
53-
{
54-
_created = DateTime.ParseExact(
55-
firstBit,
56-
DateTimeFormat,
57-
CultureInfo.InvariantCulture);
58-
}
59-
else
60-
{
61-
_created = _info.CreationTime;
62-
}
63-
64-
if (_created > DateTime.Now.Add(-TimeSpan.FromMinutes(5)))
65-
{
66-
// anything under 5 minutes old is "new" still by default
67-
_hasBeenSeen = false;
68-
}
69-
else
70-
{
71-
// everything else has been seen by default
72-
_hasBeenSeen = true;
73-
}
49+
InitializeFromFileInfo();
7450
}
7551

7652
public MessageEntry(string file)
@@ -122,6 +98,31 @@ public bool Equals(MessageEntry? other)
12298

12399
public event PropertyChangedEventHandler? PropertyChanged;
124100

101+
private void InitializeFromFileInfo()
102+
{
103+
var firstBit = _info.Name.Split(' ').FirstOrDefault();
104+
if (firstBit?.Length == DateTimeFormat.Length)
105+
{
106+
_created = DateTime.ParseExact(
107+
firstBit,
108+
DateTimeFormat,
109+
CultureInfo.InvariantCulture);
110+
}
111+
else
112+
{
113+
_created = _info.CreationTime;
114+
}
115+
116+
if (_created > DateTime.Now.Add(-TimeSpan.FromMinutes(5)))
117+
{
118+
_hasBeenSeen = false;
119+
}
120+
else
121+
{
122+
_hasBeenSeen = true;
123+
}
124+
}
125+
125126
public override string ToString()
126127
{
127128
return DisplayText;
@@ -151,4 +152,16 @@ protected virtual void OnPropertyChanged(string propertyName)
151152
propertyChangedEventHandler.Invoke(this, new PropertyChangedEventArgs(propertyName));
152153
}
153154
}
155+
156+
public MessageEntryDto ToDto()
157+
{
158+
return new MessageEntryDto
159+
{
160+
ModifiedDate = ModifiedDate,
161+
File = File,
162+
Name = Name,
163+
FileSize = FileSize,
164+
DisplayText = DisplayText,
165+
};
166+
}
154167
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Papercut
2+
//
3+
// Copyright © 2008 - 2012 Ken Robertson
4+
// Copyright © 2013 - 2025 Jaben Cargman
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
19+
namespace Papercut.Core.Domain.Message;
20+
21+
public class MessageEntryDto
22+
{
23+
public DateTime ModifiedDate { get; init; }
24+
25+
public required string File { get; init; }
26+
27+
public string? Name { get; init; }
28+
29+
public string? FileSize { get; init; }
30+
31+
public string? DisplayText { get; init; }
32+
33+
public MessageEntry ToEntry() => new(File);
34+
}

src/Papercut.Core/Domain/Message/NewMessageEvent.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,4 @@
2020

2121
namespace Papercut.Core.Domain.Message;
2222

23-
public class NewMessageEvent : IEvent
24-
{
25-
public NewMessageEvent(MessageEntry newMessage)
26-
{
27-
this.NewMessage = newMessage;
28-
}
29-
30-
public MessageEntry NewMessage { get; set; }
31-
}
23+
public record NewMessageEvent(MessageEntryDto NewMessage) : IEvent;

src/Papercut.Core/Domain/Network/EndpointDefinition.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public EndpointDefinition(
3838
StoreName storeName = StoreName.My)
3939
: this(address, port)
4040
{
41-
this.Certificate = this.LoadCertificateFromStore(
41+
this.Certificate = LoadCertificateFromStore(
4242
certificateFindType,
4343
certificateFindValue,
4444
storeLocation,
@@ -66,7 +66,7 @@ private IPAddress ParseIpAddress(string value)
6666
return IPAddress.Parse(value);
6767
}
6868

69-
private X509Certificate? LoadCertificateFromStore(
69+
private static X509Certificate2 LoadCertificateFromStore(
7070
X509FindType findType,
7171
string findValue,
7272
StoreLocation storeLocation,
@@ -102,7 +102,7 @@ private IPAddress ParseIpAddress(string value)
102102
var certificate = certificates[0];
103103

104104
// Validate certificate has private key (required for TLS server)
105-
if (certificate is X509Certificate2 cert2)
105+
if (certificate is { } cert2)
106106
{
107107
if (!cert2.HasPrivateKey)
108108
{

src/Papercut.Core/Domain/Network/IServer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public interface IServer : IDisposable, IAsyncDisposable
3131

3232
int ListenPort { get; }
3333

34-
Task StartAsync(EndpointDefinition endpoint);
34+
Task StartAsync(EndpointDefinition endpoint, CancellationToken token = default);
3535

36-
Task StopAsync();
36+
Task StopAsync(CancellationToken token = default);
3737
}

src/Papercut.Core/Domain/Paths/IPathTemplatesProvider.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,15 @@
2020

2121
namespace Papercut.Core.Domain.Paths;
2222

23+
public enum PathTemplateType
24+
{
25+
Message,
26+
Logging
27+
}
28+
2329
public interface IPathTemplatesProvider
2430
{
25-
ObservableCollection<string> MessagePathTemplates { get; }
31+
ObservableCollection<string> PathTemplates { get; }
2632

27-
ObservableCollection<string> LoggingPathTemplates { get; }
33+
PathTemplateType Type { get; }
2834
}

src/Papercut.Core/Domain/Paths/MessagePathConfigurator.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,4 @@
1818

1919
namespace Papercut.Core.Domain.Paths;
2020

21-
public class MessagePathConfigurator : PathConfiguratorBase
22-
{
23-
public MessagePathConfigurator(IPathTemplatesProvider pathTemplateProvider, ILogger logger) : base(pathTemplateProvider, logger)
24-
{
25-
}
26-
}
21+
public class MessagePathConfigurator(IPathTemplatesProvider pathTemplateProvider, ILogger logger) : PathConfiguratorBase(pathTemplateProvider, logger);

0 commit comments

Comments
 (0)