react-native-email-imap-smtp 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/react-native.config.js +1 -2
- package/windows/EmailImapSmtp/EmailImapSmtp.def +3 -0
- package/windows/EmailImapSmtp/EmailImapSmtp.vcxproj +159 -0
- package/windows/EmailImapSmtp/EmailImapSmtp.vcxproj.filters +74 -0
- package/windows/EmailImapSmtp/EmailImapSmtpModule.h +494 -0
- package/windows/{ImapProtocol.cpp → EmailImapSmtp/ImapProtocol.cpp} +1 -0
- package/windows/EmailImapSmtp/PropertySheet.props +28 -0
- package/windows/EmailImapSmtp/ReactPackageProvider.cpp +20 -0
- package/windows/EmailImapSmtp/ReactPackageProvider.h +22 -0
- package/windows/EmailImapSmtp/ReactPackageProvider.idl +13 -0
- package/windows/{SmtpProtocol.cpp → EmailImapSmtp/SmtpProtocol.cpp} +1 -0
- package/windows/{TlsSocket.cpp → EmailImapSmtp/TlsSocket.cpp} +139 -15
- package/windows/{TlsSocket.h → EmailImapSmtp/TlsSocket.h} +3 -3
- package/windows/EmailImapSmtp/pch.cpp +5 -0
- package/windows/EmailImapSmtp/pch.h +39 -0
- package/windows/EmailImapSmtp.sln +30 -0
- package/windows/ExperimentalFeatures.props +15 -0
- package/windows/EmailImapSmtpModule.h +0 -139
- /package/windows/{EmailImapSmtp.cpp → EmailImapSmtp/EmailImapSmtp.cpp} +0 -0
- /package/windows/{EmailImapSmtp.h → EmailImapSmtp/EmailImapSmtp.h} +0 -0
- /package/windows/{EmailImapSmtpModule.cpp → EmailImapSmtp/EmailImapSmtpModule.cpp} +0 -0
- /package/windows/{EmailImapSmtpPackage.cpp → EmailImapSmtp/EmailImapSmtpPackage.cpp} +0 -0
- /package/windows/{EmailImapSmtpPackage.h → EmailImapSmtp/EmailImapSmtpPackage.h} +0 -0
- /package/windows/{ImapProtocol.h → EmailImapSmtp/ImapProtocol.h} +0 -0
- /package/windows/{ProtocolDefs.h → EmailImapSmtp/ProtocolDefs.h} +0 -0
- /package/windows/{SmtpProtocol.h → EmailImapSmtp/SmtpProtocol.h} +0 -0
|
@@ -2,8 +2,132 @@
|
|
|
2
2
|
// TlsSocket.cpp — WinSock2 TCP + Schannel TLS implementation
|
|
3
3
|
// ============================================================
|
|
4
4
|
|
|
5
|
+
#include "pch.h"
|
|
5
6
|
#include "TlsSocket.h"
|
|
6
7
|
|
|
8
|
+
// Manual SSPI/Schannel declarations for UWP compat (SDK excludes these)
|
|
9
|
+
#pragma comment(lib, "ws2_32.lib")
|
|
10
|
+
#pragma comment(lib, "crypt32.lib")
|
|
11
|
+
#pragma comment(lib, "secur32.lib")
|
|
12
|
+
|
|
13
|
+
#ifndef SCHANNEL_CRED_VERSION
|
|
14
|
+
#define SECURITY_STATUS int
|
|
15
|
+
#define SEC_E_OK 0
|
|
16
|
+
#define SEC_I_CONTINUE_NEEDED 0x00090312L
|
|
17
|
+
#define SEC_E_INCOMPLETE_MESSAGE 0x80090318L
|
|
18
|
+
#define SECPKG_ATTR_STREAM_SIZES 0x00000004
|
|
19
|
+
#define SECPKG_CRED_OUTBOUND 2
|
|
20
|
+
#define SCHANNEL_CRED_VERSION 4
|
|
21
|
+
#define SP_PROT_TLS1_2 0x00000800
|
|
22
|
+
#define SCH_CRED_MANUAL_CRED_VALIDATION 0x00000008
|
|
23
|
+
#define SCH_CRED_NO_SYSTEM_MAPPER 0x00000002
|
|
24
|
+
#define SCH_CRED_NO_SERVERNAME_CHECK 0x00000004
|
|
25
|
+
#define SECBUFFER_VERSION 0
|
|
26
|
+
#define SECBUFFER_EMPTY 0
|
|
27
|
+
#define SECBUFFER_DATA 1
|
|
28
|
+
#define SECBUFFER_TOKEN 2
|
|
29
|
+
#define SECBUFFER_STREAM_HEADER 5
|
|
30
|
+
#define SECBUFFER_STREAM_TRAILER 6
|
|
31
|
+
#define SECBUFFER_EXTRA 9
|
|
32
|
+
#define SECBUFFER_MISSING 11
|
|
33
|
+
#define ISC_REQ_SEQUENCE_DETECT 0x00000008
|
|
34
|
+
#define ISC_REQ_REPLAY_DETECT 0x00000004
|
|
35
|
+
#define ISC_REQ_CONFIDENTIALITY 0x00000010
|
|
36
|
+
#define ISC_REQ_ALLOCATE_MEMORY 0x00000100
|
|
37
|
+
#define ISC_REQ_STREAM 0x00008000
|
|
38
|
+
#define ISC_REQ_MANUAL_CRED_VALIDATION 0x00080000
|
|
39
|
+
|
|
40
|
+
typedef struct _SecHandle {
|
|
41
|
+
ULONG_PTR dwLower;
|
|
42
|
+
ULONG_PTR dwUpper;
|
|
43
|
+
} SecHandle;
|
|
44
|
+
typedef SecHandle CredHandle;
|
|
45
|
+
typedef SecHandle CtxtHandle;
|
|
46
|
+
|
|
47
|
+
typedef struct _SecBuffer {
|
|
48
|
+
unsigned long cbBuffer;
|
|
49
|
+
unsigned long BufferType;
|
|
50
|
+
void* pvBuffer;
|
|
51
|
+
} SecBuffer;
|
|
52
|
+
|
|
53
|
+
typedef struct _SecBufferDesc {
|
|
54
|
+
unsigned long ulVersion;
|
|
55
|
+
unsigned long cBuffers;
|
|
56
|
+
SecBuffer* pBuffers;
|
|
57
|
+
} SecBufferDesc;
|
|
58
|
+
|
|
59
|
+
typedef struct _SCHANNEL_CRED {
|
|
60
|
+
DWORD dwVersion;
|
|
61
|
+
DWORD cCreds;
|
|
62
|
+
void* paCred;
|
|
63
|
+
void* hRootStore;
|
|
64
|
+
DWORD cMappers;
|
|
65
|
+
void* aphMappers;
|
|
66
|
+
DWORD cSupportedAlgs;
|
|
67
|
+
void* paSupportedAlgs;
|
|
68
|
+
DWORD dwFlags;
|
|
69
|
+
DWORD dwCredFormat;
|
|
70
|
+
DWORD grbitEnabledProtocols;
|
|
71
|
+
DWORD dwMinimumCipherStrength;
|
|
72
|
+
DWORD dwMaximumCipherStrength;
|
|
73
|
+
} SCHANNEL_CRED;
|
|
74
|
+
|
|
75
|
+
typedef struct _SecPkgContext_StreamSizes {
|
|
76
|
+
unsigned long cbHeader;
|
|
77
|
+
unsigned long cbTrailer;
|
|
78
|
+
unsigned long cbMaximumMessage;
|
|
79
|
+
unsigned long cBuffers;
|
|
80
|
+
unsigned long cbBlockSize;
|
|
81
|
+
unsigned long cbMaxTrailer;
|
|
82
|
+
} SecPkgContext_StreamSizes;
|
|
83
|
+
|
|
84
|
+
typedef struct _SecPkgContext_Sizes {
|
|
85
|
+
unsigned long cbMaxToken;
|
|
86
|
+
unsigned long cbMaxSignature;
|
|
87
|
+
unsigned long cbBlockSize;
|
|
88
|
+
unsigned long cbMaxTrailer;
|
|
89
|
+
} SecPkgContext_Sizes;
|
|
90
|
+
|
|
91
|
+
typedef struct _TimeStamp {
|
|
92
|
+
LONG LowPart;
|
|
93
|
+
LONG HighPart;
|
|
94
|
+
} TimeStamp;
|
|
95
|
+
|
|
96
|
+
#ifndef SEC_ENTRY
|
|
97
|
+
#define SEC_ENTRY
|
|
98
|
+
#endif
|
|
99
|
+
extern "C" {
|
|
100
|
+
int SEC_ENTRY AcquireCredentialsHandleW(LPWSTR, LPWSTR, unsigned long, void*, void*, void*, void*, CredHandle*, TimeStamp*);
|
|
101
|
+
int SEC_ENTRY AcquireCredentialsHandleA(LPSTR, LPSTR, unsigned long, void*, void*, void*, void*, CredHandle*, TimeStamp*);
|
|
102
|
+
int SEC_ENTRY InitializeSecurityContextA(CredHandle*, void*, LPSTR, unsigned long, unsigned long, unsigned long, SecBufferDesc*, unsigned long, CtxtHandle*, SecBufferDesc*, unsigned long*, TimeStamp*);
|
|
103
|
+
int SEC_ENTRY InitializeSecurityContextW(CredHandle*, void*, LPWSTR, unsigned long, unsigned long, unsigned long, SecBufferDesc*, unsigned long, CtxtHandle*, SecBufferDesc*, unsigned long*, TimeStamp*);
|
|
104
|
+
int SEC_ENTRY DeleteSecurityContext(CtxtHandle*);
|
|
105
|
+
int SEC_ENTRY FreeCredentialsHandle(CredHandle*);
|
|
106
|
+
int SEC_ENTRY FreeContextBuffer(void*);
|
|
107
|
+
int SEC_ENTRY EncryptMessage(CtxtHandle*, unsigned long, SecBufferDesc*, unsigned long);
|
|
108
|
+
int SEC_ENTRY DecryptMessage(CtxtHandle*, SecBufferDesc*, unsigned long, void*);
|
|
109
|
+
int SEC_ENTRY QueryContextAttributesW(CtxtHandle*, unsigned long, void*);
|
|
110
|
+
int SEC_ENTRY QueryContextAttributesA(CtxtHandle*, unsigned long, void*);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
|
|
114
|
+
#define UNISP_NAME UNISP_NAME_A
|
|
115
|
+
#define AcquireCredentialsHandle AcquireCredentialsHandleA
|
|
116
|
+
#define QueryContextAttributes QueryContextAttributesA
|
|
117
|
+
|
|
118
|
+
#endif // SCHANNEL_CRED_VERSION
|
|
119
|
+
|
|
120
|
+
// Cast helpers: uint8_t[] members -> typed references for SSPI API calls
|
|
121
|
+
#ifdef SCHANNEL_CRED_VERSION
|
|
122
|
+
#define credHandle (*reinterpret_cast<CredHandle*>(m_credHandle))
|
|
123
|
+
#define ctxtHandle (*reinterpret_cast<CtxtHandle*>(m_ctxtHandle))
|
|
124
|
+
#define streamSizes (*reinterpret_cast<SecPkgContext_StreamSizes*>(m_streamSizes))
|
|
125
|
+
#else
|
|
126
|
+
#define credHandle m_credHandle
|
|
127
|
+
#define ctxtHandle m_ctxtHandle
|
|
128
|
+
#define streamSizes m_streamSizes
|
|
129
|
+
#endif
|
|
130
|
+
|
|
7
131
|
#include <sstream>
|
|
8
132
|
#include <cstring>
|
|
9
133
|
#include <chrono>
|
|
@@ -249,11 +373,11 @@ bool TlsSocket::connect(const std::string& host, int port, int timeoutMs, bool c
|
|
|
249
373
|
|
|
250
374
|
void TlsSocket::disconnectInternal() {
|
|
251
375
|
if (m_hasCtxtHandle) {
|
|
252
|
-
DeleteSecurityContext(&
|
|
376
|
+
DeleteSecurityContext(&ctxtHandle);
|
|
253
377
|
m_hasCtxtHandle = false;
|
|
254
378
|
}
|
|
255
379
|
if (m_hasCredHandle) {
|
|
256
|
-
FreeCredentialsHandle(&
|
|
380
|
+
FreeCredentialsHandle(&credHandle);
|
|
257
381
|
m_hasCredHandle = false;
|
|
258
382
|
}
|
|
259
383
|
if (m_socket != INVALID_SOCKET) {
|
|
@@ -298,7 +422,7 @@ bool TlsSocket::initializeSchannel() {
|
|
|
298
422
|
&schannelCred,
|
|
299
423
|
nullptr,
|
|
300
424
|
nullptr,
|
|
301
|
-
&
|
|
425
|
+
&credHandle,
|
|
302
426
|
&expiry
|
|
303
427
|
);
|
|
304
428
|
|
|
@@ -337,7 +461,7 @@ bool TlsSocket::performClientHandshake() {
|
|
|
337
461
|
TimeStamp expiry;
|
|
338
462
|
|
|
339
463
|
status = InitializeSecurityContextW(
|
|
340
|
-
&
|
|
464
|
+
&credHandle,
|
|
341
465
|
nullptr,
|
|
342
466
|
const_cast<wchar_t*>(wServerName.c_str()),
|
|
343
467
|
flags,
|
|
@@ -345,7 +469,7 @@ bool TlsSocket::performClientHandshake() {
|
|
|
345
469
|
0,
|
|
346
470
|
nullptr,
|
|
347
471
|
0,
|
|
348
|
-
&
|
|
472
|
+
&ctxtHandle,
|
|
349
473
|
&outDesc,
|
|
350
474
|
&outFlags,
|
|
351
475
|
&expiry
|
|
@@ -404,8 +528,8 @@ bool TlsSocket::performClientHandshake() {
|
|
|
404
528
|
outBuffers[0].BufferType = SECBUFFER_TOKEN;
|
|
405
529
|
|
|
406
530
|
status = InitializeSecurityContextW(
|
|
407
|
-
&
|
|
408
|
-
&
|
|
531
|
+
&credHandle,
|
|
532
|
+
&ctxtHandle,
|
|
409
533
|
const_cast<wchar_t*>(wServerName.c_str()),
|
|
410
534
|
flags,
|
|
411
535
|
0,
|
|
@@ -477,7 +601,7 @@ bool TlsSocket::performClientHandshake() {
|
|
|
477
601
|
}
|
|
478
602
|
|
|
479
603
|
if (status == SEC_E_OK) {
|
|
480
|
-
QueryContextAttributes(&
|
|
604
|
+
QueryContextAttributes(&ctxtHandle, SECPKG_ATTR_STREAM_SIZES, &streamSizes);
|
|
481
605
|
m_hasCtxtHandle = true;
|
|
482
606
|
// Save any extra (unconsumed) data to m_receiveBuffer so the caller
|
|
483
607
|
// can read it (e.g. IMAP greeting piggybacked on the handshake).
|
|
@@ -505,22 +629,22 @@ bool TlsSocket::performClientHandshake() {
|
|
|
505
629
|
bool TlsSocket::encryptMessage(const std::string& plaintext, std::vector<char>& ciphertext) {
|
|
506
630
|
if (!m_hasCtxtHandle) return false;
|
|
507
631
|
|
|
508
|
-
int needed =
|
|
632
|
+
int needed = streamSizes.cbHeader + static_cast<int>(plaintext.size()) + streamSizes.cbTrailer;
|
|
509
633
|
std::vector<char> msg(needed);
|
|
510
634
|
|
|
511
635
|
SecBuffer buffers[4];
|
|
512
|
-
buffers[0].cbBuffer =
|
|
636
|
+
buffers[0].cbBuffer = streamSizes.cbHeader;
|
|
513
637
|
buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
|
|
514
638
|
buffers[0].pvBuffer = msg.data();
|
|
515
639
|
|
|
516
640
|
buffers[1].cbBuffer = static_cast<unsigned long>(plaintext.size());
|
|
517
641
|
buffers[1].BufferType = SECBUFFER_DATA;
|
|
518
|
-
buffers[1].pvBuffer = msg.data() +
|
|
642
|
+
buffers[1].pvBuffer = msg.data() + streamSizes.cbHeader;
|
|
519
643
|
memcpy(buffers[1].pvBuffer, plaintext.data(), plaintext.size());
|
|
520
644
|
|
|
521
|
-
buffers[2].cbBuffer =
|
|
645
|
+
buffers[2].cbBuffer = streamSizes.cbTrailer;
|
|
522
646
|
buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
|
|
523
|
-
buffers[2].pvBuffer = msg.data() +
|
|
647
|
+
buffers[2].pvBuffer = msg.data() + streamSizes.cbHeader + plaintext.size();
|
|
524
648
|
|
|
525
649
|
buffers[3].cbBuffer = 0;
|
|
526
650
|
buffers[3].BufferType = SECBUFFER_EMPTY;
|
|
@@ -530,7 +654,7 @@ bool TlsSocket::encryptMessage(const std::string& plaintext, std::vector<char>&
|
|
|
530
654
|
desc.cBuffers = 4;
|
|
531
655
|
desc.pBuffers = buffers;
|
|
532
656
|
|
|
533
|
-
SECURITY_STATUS status = EncryptMessage(&
|
|
657
|
+
SECURITY_STATUS status = EncryptMessage(&ctxtHandle, 0, &desc, 0);
|
|
534
658
|
if (status != SEC_E_OK) return false;
|
|
535
659
|
|
|
536
660
|
int totalSize = buffers[0].cbBuffer + buffers[1].cbBuffer + buffers[2].cbBuffer;
|
|
@@ -563,7 +687,7 @@ int TlsSocket::decryptMessage(std::vector<char>& buffer, std::vector<char>& plai
|
|
|
563
687
|
desc.cBuffers = 4;
|
|
564
688
|
desc.pBuffers = buffers;
|
|
565
689
|
|
|
566
|
-
SECURITY_STATUS status = DecryptMessage(&
|
|
690
|
+
SECURITY_STATUS status = DecryptMessage(&ctxtHandle, &desc, 0, nullptr);
|
|
567
691
|
if (status == SEC_E_INCOMPLETE_MESSAGE) {
|
|
568
692
|
// need more data
|
|
569
693
|
return 0; // need more data
|
|
@@ -58,13 +58,13 @@ public:
|
|
|
58
58
|
private:
|
|
59
59
|
SOCKET m_socket = INVALID_SOCKET;
|
|
60
60
|
bool m_tls = false;
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
uint8_t m_credHandle[16];
|
|
62
|
+
uint8_t m_ctxtHandle[16];
|
|
63
63
|
bool m_hasCredHandle = false;
|
|
64
64
|
bool m_hasCtxtHandle = false;
|
|
65
65
|
std::string m_serverName;
|
|
66
66
|
bool m_checkCertificate = true;
|
|
67
|
-
|
|
67
|
+
uint8_t m_streamSizes[24];
|
|
68
68
|
|
|
69
69
|
std::mutex m_mutex;
|
|
70
70
|
int m_lastError = 0; // stores WSAGetLastError() on failure
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// pch.h — Precompiled Header
|
|
3
|
+
// ============================================================
|
|
4
|
+
|
|
5
|
+
#pragma once
|
|
6
|
+
|
|
7
|
+
#define NOMINMAX
|
|
8
|
+
#define WIN32_LEAN_AND_MEAN
|
|
9
|
+
#define SECURITY_WIN32
|
|
10
|
+
|
|
11
|
+
#include <windows.h>
|
|
12
|
+
#include <winsock2.h>
|
|
13
|
+
#include <ws2tcpip.h>
|
|
14
|
+
#include <winrt/Microsoft.ReactNative.h>
|
|
15
|
+
#include <winrt/Windows.Foundation.h>
|
|
16
|
+
#include <winrt/Windows.Foundation.Collections.h>
|
|
17
|
+
|
|
18
|
+
#include <string>
|
|
19
|
+
#include <vector>
|
|
20
|
+
#include <map>
|
|
21
|
+
#include <memory>
|
|
22
|
+
#include <mutex>
|
|
23
|
+
#include <thread>
|
|
24
|
+
#include <atomic>
|
|
25
|
+
#include <condition_variable>
|
|
26
|
+
#include <functional>
|
|
27
|
+
#include <optional>
|
|
28
|
+
#include <variant>
|
|
29
|
+
#include <set>
|
|
30
|
+
#include <regex>
|
|
31
|
+
#include <sstream>
|
|
32
|
+
#include <cctype>
|
|
33
|
+
#include <algorithm>
|
|
34
|
+
#include <chrono>
|
|
35
|
+
#include <cstring>
|
|
36
|
+
#include <cstdint>
|
|
37
|
+
#include <ctime>
|
|
38
|
+
#include <iomanip>
|
|
39
|
+
#include <cstdlib>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
2
|
+
# Visual Studio Version 17
|
|
3
|
+
VisualStudioVersion = 17.0.31903.59
|
|
4
|
+
MinimumVisualStudioVersion = 10.0.40219.1
|
|
5
|
+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmailImapSmtp", "EmailImapSmtp\EmailImapSmtp.vcxproj", "{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}"
|
|
6
|
+
EndProject
|
|
7
|
+
Global
|
|
8
|
+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
9
|
+
Debug|x64 = Debug|x64
|
|
10
|
+
Debug|x86 = Debug|x86
|
|
11
|
+
Debug|ARM64 = Debug|ARM64
|
|
12
|
+
Release|x64 = Release|x64
|
|
13
|
+
Release|x86 = Release|x86
|
|
14
|
+
Release|ARM64 = Release|ARM64
|
|
15
|
+
EndGlobalSection
|
|
16
|
+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
17
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Debug|x64.ActiveCfg = Debug|x64
|
|
18
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Debug|x64.Build.0 = Debug|x64
|
|
19
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Debug|x86.ActiveCfg = Debug|x86
|
|
20
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Debug|x86.Build.0 = Debug|x86
|
|
21
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
|
22
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Debug|ARM64.Build.0 = Debug|ARM64
|
|
23
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Release|x64.ActiveCfg = Release|x64
|
|
24
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Release|x64.Build.0 = Release|x64
|
|
25
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Release|x86.ActiveCfg = Release|x86
|
|
26
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Release|x86.Build.0 = Release|x86
|
|
27
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Release|ARM64.ActiveCfg = Release|ARM64
|
|
28
|
+
{A3B8E7F1-2C4D-5E6F-8A9B-0C1D2E3F4A5B}.Release|ARM64.Build.0 = Release|ARM64
|
|
29
|
+
EndGlobalSection
|
|
30
|
+
EndGlobal
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
3
|
+
<PropertyGroup Label="ReactNativeWindowsExperimentalFeatures">
|
|
4
|
+
<!-- 不使用 Hermes -->
|
|
5
|
+
<UseHermes>false</UseHermes>
|
|
6
|
+
<!-- 不使用 WinUI 3 -->
|
|
7
|
+
<UseWinUI3>false</UseWinUI3>
|
|
8
|
+
<!-- 不使用实验性 NuGet -->
|
|
9
|
+
<UseExperimentalNuget>true</UseExperimentalNuget>
|
|
10
|
+
<RnwNewArch>true</RnwNewArch>
|
|
11
|
+
<RunCodegenWindows>false</RunCodegenWindows>
|
|
12
|
+
<!-- 不使用 Folly (不再需要) -->
|
|
13
|
+
<UseFolly>false</UseFolly>
|
|
14
|
+
</PropertyGroup>
|
|
15
|
+
</Project>
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
// ============================================================
|
|
2
|
-
// EmailImapSmtpModule.h — Windows TurboModule 实现
|
|
3
|
-
// 通过 JSON 字符串与 JS 层通信,内部调用协议层 C++ 代码
|
|
4
|
-
// ============================================================
|
|
5
|
-
|
|
6
|
-
#pragma once
|
|
7
|
-
|
|
8
|
-
#include <string>
|
|
9
|
-
#include <unordered_map>
|
|
10
|
-
#include <memory>
|
|
11
|
-
#include <mutex>
|
|
12
|
-
|
|
13
|
-
#include "winrt/Microsoft.ReactNative.h"
|
|
14
|
-
#include "NativeModules.h"
|
|
15
|
-
|
|
16
|
-
#include "ImapProtocol.h"
|
|
17
|
-
#include "SmtpProtocol.h"
|
|
18
|
-
|
|
19
|
-
namespace winrt::EmailImapSmtp {
|
|
20
|
-
|
|
21
|
-
struct SessionState {
|
|
22
|
-
std::unique_ptr<emailimap::ImapClient> imapClient;
|
|
23
|
-
std::unique_ptr<emailimap::SmtpClient> smtpClient;
|
|
24
|
-
bool imapConnected = false;
|
|
25
|
-
bool smtpConnected = false;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
REACT_MODULE(EmailImapSmtpModule);
|
|
29
|
-
struct EmailImapSmtpModule {
|
|
30
|
-
// ─── Session 管理 ─────────────────────────────────────
|
|
31
|
-
std::unordered_map<std::string, std::shared_ptr<SessionState>> m_sessions;
|
|
32
|
-
std::mutex m_mutex;
|
|
33
|
-
int m_nextId = 1;
|
|
34
|
-
|
|
35
|
-
std::string createSession() {
|
|
36
|
-
auto state = std::make_shared<SessionState>();
|
|
37
|
-
state->imapClient = std::make_unique<emailimap::ImapClient>();
|
|
38
|
-
state->smtpClient = std::make_unique<emailimap::SmtpClient>();
|
|
39
|
-
std::string id = "sess_" + std::to_string(m_nextId++);
|
|
40
|
-
std::lock_guard<std::mutex> lock(m_mutex);
|
|
41
|
-
m_sessions[id] = state;
|
|
42
|
-
return id;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
std::shared_ptr<SessionState> getSession(const std::string& id) {
|
|
46
|
-
std::lock_guard<std::mutex> lock(m_mutex);
|
|
47
|
-
auto it = m_sessions.find(id);
|
|
48
|
-
if (it == m_sessions.end()) return nullptr;
|
|
49
|
-
return it->second;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
void removeSession(const std::string& id) {
|
|
53
|
-
std::lock_guard<std::mutex> lock(m_mutex);
|
|
54
|
-
m_sessions.erase(id);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// ─── IMAP 连接 ────────────────────────────────────────
|
|
58
|
-
|
|
59
|
-
REACT_METHOD(imapConnect);
|
|
60
|
-
std::string imapConnect(const std::string& configJson) noexcept {
|
|
61
|
-
try {
|
|
62
|
-
auto config = emailimap::ConnectionConfig{};
|
|
63
|
-
// TODO: parse configJson → config
|
|
64
|
-
// 使用 JSON 库(如 nlohmann/json)解析
|
|
65
|
-
|
|
66
|
-
auto sessionId = createSession();
|
|
67
|
-
auto session = getSession(sessionId);
|
|
68
|
-
std::string error;
|
|
69
|
-
if (session->imapClient->connect(config, error)) {
|
|
70
|
-
session->imapConnected = true;
|
|
71
|
-
return "{\"success\":true,\"sessionId\":\"" + sessionId + "\"}";
|
|
72
|
-
}
|
|
73
|
-
removeSession(sessionId);
|
|
74
|
-
return "{\"success\":false,\"error\":\"" + escapeJson(error) + "\"}";
|
|
75
|
-
} catch (const std::exception& e) {
|
|
76
|
-
return "{\"success\":false,\"error\":\"" + escapeJson(e.what()) + "\"}";
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
REACT_METHOD(imapDisconnect);
|
|
81
|
-
void imapDisconnect(const std::string& sessionId) noexcept {
|
|
82
|
-
auto session = getSession(sessionId);
|
|
83
|
-
if (session && session->imapConnected) {
|
|
84
|
-
session->imapClient->disconnect();
|
|
85
|
-
session->imapConnected = false;
|
|
86
|
-
}
|
|
87
|
-
removeSession(sessionId);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// ─── SMTP ──────────────────────────────────────────────
|
|
91
|
-
|
|
92
|
-
REACT_METHOD(smtpConnect);
|
|
93
|
-
std::string smtpConnect(const std::string& configJson) noexcept {
|
|
94
|
-
try {
|
|
95
|
-
auto config = emailimap::SmtpConnectionConfig{};
|
|
96
|
-
// TODO: parse configJson → config
|
|
97
|
-
|
|
98
|
-
auto sessionId = createSession();
|
|
99
|
-
auto session = getSession(sessionId);
|
|
100
|
-
std::string error;
|
|
101
|
-
if (session->smtpClient->connect(config, error)) {
|
|
102
|
-
session->smtpConnected = true;
|
|
103
|
-
return "{\"success\":true,\"sessionId\":\"" + sessionId + "\"}";
|
|
104
|
-
}
|
|
105
|
-
removeSession(sessionId);
|
|
106
|
-
return "{\"success\":false,\"error\":\"" + escapeJson(error) + "\"}";
|
|
107
|
-
} catch (const std::exception& e) {
|
|
108
|
-
return "{\"success\":false,\"error\":\"" + escapeJson(e.what()) + "\"}";
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
REACT_METHOD(smtpDisconnect);
|
|
113
|
-
void smtpDisconnect(const std::string& sessionId) noexcept {
|
|
114
|
-
auto session = getSession(sessionId);
|
|
115
|
-
if (session && session->smtpConnected) {
|
|
116
|
-
session->smtpClient->disconnect();
|
|
117
|
-
session->smtpConnected = false;
|
|
118
|
-
}
|
|
119
|
-
removeSession(sessionId);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
private:
|
|
123
|
-
static std::string escapeJson(const std::string& s) {
|
|
124
|
-
std::string result;
|
|
125
|
-
for (char c : s) {
|
|
126
|
-
switch (c) {
|
|
127
|
-
case '"': result += "\\\""; break;
|
|
128
|
-
case '\\': result += "\\\\"; break;
|
|
129
|
-
case '\n': result += "\\n"; break;
|
|
130
|
-
case '\r': result += "\\r"; break;
|
|
131
|
-
case '\t': result += "\\t"; break;
|
|
132
|
-
default: result += c;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return result;
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
} // namespace winrt::EmailImapSmtp
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|