Skip to content

Commit d24b918

Browse files
authoredMar 4, 2018
Merge pull request ChangemakerStudios#97 from ChangemakerStudios/develop
Merge latest into Master
2 parents 3ae9daf + 8af84f3 commit d24b918

40 files changed

+1128
-2074
lines changed
 

‎README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ The Simple SMTP Desktop Email Receiver
1010
Ever need to test emails from an application or web site but don't want them accidently being sent or having to deal with the hassle of setting up a test email server? Papercut is a quick email viewer with a built-in SMTP server designed to only receive messages. It doesn't enforce any restrictions how you send your email. It allows you to view the whole email-chilada: body, html, headers, attachment down to the naughty raw bits. It can be set to run on startup and sits quietly minimized in the tray giving you a balloon popup when a new message arrives.
1111

1212
## Download Now
13-
#### [ClickOnce](https://papercut.codeplex.com/downloads/get/clickOnce/Papercut.application) | [Releases (zip files)](https://github.com/ChangemakerStudios/Papercut/releases)
13+
#### [Latest Release](https://github.com/ChangemakerStudios/Papercut/releases)
14+
Download Papercut.Setup.exe installer.
1415

1516
## Features
1617
#### Instant Feedback When New Email Arrives

‎appveyor.yml

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
os: Visual Studio 2017
22

3-
version: 5.0.{build}
3+
version: 5.1.{build}
44

55
configuration: Release
66

7+
assembly_info:
8+
patch: true
9+
file: '**\AssemblyInfo.*'
10+
assembly_version: '{version}'
11+
assembly_file_version: '{version}'
12+
assembly_informational_version: '{version}'
13+
14+
dotnet_csproj:
15+
patch: true
16+
file: '**\*.csproj'
17+
version: '{version}'
18+
package_version: '{version}'
19+
assembly_version: '{version}'
20+
file_version: '{version}'
21+
informational_version: '{version}'
22+
723
before_build:
824
- nuget restore
925

‎src/Papercut.Module.Seq/SeqLoggingModule.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
// Papercut
2-
//
2+
//
33
// Copyright © 2008 - 2012 Ken Robertson
44
// Copyright © 2013 - 2017 Jaben Cargman
5-
//
5+
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
88
// You may obtain a copy of the License at
9-
//
9+
//
1010
// http://www.apache.org/licenses/LICENSE-2.0
11-
//
11+
//
1212
// Unless required by applicable law or agreed to in writing, software
1313
// distributed under the License is distributed on an "AS IS" BASIS,
1414
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1515
// See the License for the specific language governing permissions and
16-
// limitations under the License.
16+
// limitations under the License.
1717

1818
namespace Papercut.Module.Seq
1919
{

‎src/Papercut.Module.WebUI/Controllers/MessageController.cs

-74
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// Papercut
2+
//
3+
// Copyright © 2008 - 2012 Ken Robertson
4+
// Copyright © 2013 - 2017 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.Module.WebUI.Controllers
20+
{
21+
using System.Linq;
22+
using System.Net;
23+
using System.Net.Http;
24+
using System.Net.Http.Headers;
25+
using System.Net.Mime;
26+
using System.Web.Http;
27+
using Helpers;
28+
using Message;
29+
using MimeKit;
30+
using Models;
31+
using Message.Helpers;
32+
using System;
33+
using System.Collections.Generic;
34+
using System.IO;
35+
36+
using Common.Extensions;
37+
38+
public class MessagesController : ApiController
39+
{
40+
readonly MessageRepository messageRepository;
41+
readonly MimeMessageLoader messageLoader;
42+
43+
public MessagesController(MessageRepository messageRepository, MimeMessageLoader messageLoader)
44+
{
45+
this.messageRepository = messageRepository;
46+
this.messageLoader = messageLoader;
47+
}
48+
49+
[HttpGet]
50+
public HttpResponseMessage GetAll(int limit = 10, int start = 0)
51+
{
52+
var messageEntries = messageRepository.LoadMessages();
53+
54+
var messages = messageEntries
55+
.OrderByDescending(msg => msg.ModifiedDate)
56+
.Skip(start)
57+
.Take(limit)
58+
.Select(e => MimeMessageEntry.RefDto.CreateFrom(new MimeMessageEntry(e, messageLoader.LoadMailMessage(e))))
59+
.ToList();
60+
61+
return Request.CreateResponse(HttpStatusCode.OK, new
62+
{
63+
TotalMessageCount = messageEntries.Count,
64+
Messages = messages
65+
});
66+
}
67+
68+
[HttpDelete]
69+
public HttpResponseMessage DeleteAll()
70+
{
71+
messageRepository.LoadMessages()
72+
.ForEach(msg =>
73+
{
74+
try
75+
{
76+
messageRepository.DeleteMessage(msg);
77+
}catch {}
78+
});
79+
80+
return Request.CreateResponse(HttpStatusCode.OK);
81+
}
82+
83+
[HttpGet]
84+
public HttpResponseMessage Get(string id)
85+
{
86+
var messageEntry = messageRepository.LoadMessages().FirstOrDefault(msg => msg.Name == id);
87+
if (messageEntry == null)
88+
{
89+
return Request.CreateResponse(HttpStatusCode.NotFound);
90+
}
91+
92+
var dto = MimeMessageEntry.DetailDto.CreateFrom(new MimeMessageEntry(messageEntry, messageLoader.LoadMailMessage(messageEntry)));
93+
return Request.CreateResponse(HttpStatusCode.OK, dto);
94+
}
95+
96+
[HttpGet]
97+
public HttpResponseMessage DownloadRaw(string messageId)
98+
{
99+
var messageEntry = messageRepository.LoadMessages().FirstOrDefault(msg => msg.Name == messageId);
100+
if (messageEntry == null)
101+
{
102+
return Request.CreateResponse(HttpStatusCode.NotFound);
103+
}
104+
105+
var response = Request.CreateResponse(HttpStatusCode.OK);
106+
response.Content = new StreamContent(File.OpenRead(messageEntry.File));
107+
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(DispositionTypeNames.Attachment)
108+
{
109+
FileName = Uri.EscapeDataString(messageId)
110+
};
111+
response.Content.Headers.ContentType = new MediaTypeHeaderValue("message/rfc822");
112+
return response;
113+
}
114+
115+
[HttpGet]
116+
public HttpResponseMessage DownloadSection(string messageId, int index)
117+
{
118+
return DownloadSection(messageId, sections => (index >=0 && index < sections.Count ? sections[index] : null));
119+
}
120+
121+
[HttpGet]
122+
public HttpResponseMessage DownloadSectionContent(string messageId, string contentId)
123+
{
124+
return DownloadSection(messageId, (sections) => sections.FirstOrDefault(s => s.ContentId == contentId));
125+
}
126+
127+
HttpResponseMessage DownloadSection(string messageId, Func<List<MimePart>, MimePart> findSection)
128+
{
129+
var messageEntry = messageRepository.LoadMessages().FirstOrDefault(msg => msg.Name == messageId);
130+
if (messageEntry == null)
131+
{
132+
return Request.CreateResponse(HttpStatusCode.NotFound);
133+
}
134+
135+
var mimeMessage = new MimeMessageEntry(messageEntry, messageLoader.LoadMailMessage(messageEntry));
136+
var sections = mimeMessage.MailMessage.BodyParts.OfType<MimePart>().ToList();
137+
138+
var mimePart = findSection(sections);
139+
if (mimePart == null)
140+
{
141+
return Request.CreateResponse(HttpStatusCode.NotFound);
142+
}
143+
144+
var response = new MimePartResponseMessage(Request, mimePart.ContentObject);
145+
var filename = mimePart.FileName ?? mimePart.ContentId ?? Guid.NewGuid().ToString();
146+
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(DispositionTypeNames.Attachment)
147+
{
148+
FileName = Uri.EscapeDataString(FileHelper.NormalizeFilename(filename))
149+
};
150+
response.Content.Headers.ContentType = new MediaTypeHeaderValue($"{mimePart.ContentType.MediaType}/{mimePart.ContentType.MediaSubtype}");
151+
return response;
152+
}
153+
}
154+
}

‎src/Papercut.Module.WebUI/Controllers/StaticContentController.cs

+26-1
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,19 @@ namespace Papercut.Module.WebUI.Controllers
1010
using System.Net.Http.Headers;
1111
using System.Reflection;
1212
using System.Web.Http;
13-
13+
using System.Web.Http.Controllers;
14+
using WebApi.OutputCache.V2;
1415

1516
public class StaticContentController: ApiController
1617
{
1718

19+
[CacheOutput(
20+
#if DEBUG
21+
ClientTimeSpan = 30,
22+
#else
23+
ClientTimeSpan = 600,
24+
#endif
25+
ServerTimeSpan = 86400, CacheKeyGenerator= typeof(PapercutResourceKeyGenerator))]
1826
public HttpResponseMessage Get()
1927
{
2028
var resourceName = GetRequetedResourceName(Request.RequestUri);
@@ -88,5 +96,22 @@ static string GetMimeType(string filename)
8896
{ "woff2", "application/font-woff2" },
8997
};
9098

99+
class PapercutResourceKeyGenerator : DefaultCacheKeyGenerator
100+
{
101+
static string AssemblyVersion;
102+
static PapercutResourceKeyGenerator()
103+
{
104+
AssemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
105+
}
106+
107+
public override string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, bool excludeQueryString = false)
108+
{
109+
var requstUri = context.Request.RequestUri;
110+
int hashCode = string.Concat("PapercutResource", AssemblyVersion, requstUri).GetHashCode();
111+
112+
return (hashCode ^ 0x10000).ToString("x2");
113+
}
114+
}
115+
91116
}
92117
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Papercut
2+
//
3+
// Copyright © 2008 - 2012 Ken Robertson
4+
// Copyright © 2013 - 2017 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.Module.WebUI.Helpers
20+
{
21+
using System.IO;
22+
using System.Linq;
23+
24+
class FileHelper
25+
{
26+
public static string NormalizeFilename(string filename)
27+
{
28+
var validFilename = RemoveInvalidFileNameChars(filename);
29+
return validFilename.Replace(" ", "_");
30+
}
31+
32+
static string RemoveInvalidFileNameChars(string filename)
33+
{
34+
return Path.GetInvalidFileNameChars().Aggregate(filename,
35+
(current, invalidChar) => current.Replace(invalidChar.ToString(), string.Empty));
36+
}
37+
38+
}
39+
}

0 commit comments

Comments
 (0)
Please sign in to comment.