Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
SmtpS2SEndpoint.cs
1using System;
3using System.Net.Mail;
4using System.Text;
5using System.Threading.Tasks;
6using System.Xml;
7using Waher.Content;
13using Waher.Events;
19
21{
26 {
27 private static Cache<string, OutgoingMail> outgoingMails;
28 private readonly SmtpServer smtpServer;
29 private readonly XmppServer xmppServer;
30
31 static SmtpS2SEndpoint()
32 {
33 outgoingMails = new Cache<string, OutgoingMail>(int.MaxValue, TimeSpan.FromHours(1), TimeSpan.FromMinutes(1), true);
34 outgoingMails.Removed += OutgoingMails_Removed;
35
36 Log.Terminating += (Sender, e) =>
37 {
38 outgoingMails?.Dispose();
39 outgoingMails = null;
40 return Task.CompletedTask;
41 };
42 }
43
54 {
55 this.smtpServer = SmtpServer;
56 this.xmppServer = XmppServer;
57 }
58
62 public bool TrustServer => false;
63
67 public override string Type => "SMTP";
68
70 public override async Task<bool> Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
71 {
72 if (string.Compare(Type, "chat", true) == 0)
73 {
74 string Key = From.Address + " | " + To.Address;
75 outgoingMails.TryGetValue(Key, out OutgoingMail Mail);
76
77 try
78 {
79 Stanza Stanza = XmppServer.ToStanza("message", Type, Id, To, From, Language, ContentXml);
80 List<EmbeddedContent> EmbeddedContent = null;
81 string Text = null;
82 string Html = null;
83 string Markdown = null;
84 string Subject = null;
85 string ReplaceId = null;
86 bool Immediate = false;
87
88 foreach (XmlNode N in Stanza.StanzaElement.ChildNodes)
89 {
90 if (N is XmlElement E)
91 {
92 switch (E.LocalName)
93 {
94 case "subject":
95 Subject = E.InnerText;
96 break;
97
98 case "body":
99 Text = E.InnerText;
100 break;
101
102 case "replace":
103 if (E.NamespaceURI == "urn:xmpp:message-correct:0")
104 ReplaceId = XML.Attribute(E, "id");
105 break;
106
107 case "html":
108 foreach (XmlNode N2 in E.ChildNodes)
109 {
110 if (N2 is XmlElement E2 && E2.LocalName == "body")
111 {
112 Html = E.InnerXml;
113 break;
114 }
115 }
116 break;
117
118 case "content":
119 switch (E.NamespaceURI)
120 {
122 switch (XML.Attribute(E, "type").ToLower())
123 {
125 Text = E.InnerText;
126 break;
127
129 Html = E.InnerText;
130 break;
131
133 Markdown = E.InnerText;
134 break;
135 }
136 break;
137
139 EmbeddedContent ??= new List<EmbeddedContent>();
140
141 byte[] Bin = Convert.FromBase64String(E.InnerText);
142
144 {
145 ID = XML.Attribute(E, "cid"),
146 ContentType = XML.Attribute(E, "type"),
147 Disposition = XML.Attribute(E, "disposition", ContentDisposition.Unknown),
148 Name = XML.Attribute(E, "name"),
149 FileName = XML.Attribute(E, "fileName"),
150 Description = XML.Attribute(E, "description"),
151 Size = Bin.Length,
152 TransferDecoded = Bin
153 });
154 break;
155 }
156 break;
157
158 case "immediate":
159 if (E.NamespaceURI == XmppServer.MailNamespace)
160 Immediate = true;
161 break;
162 }
163 }
164 }
165
166 if (!(Markdown is null) && (Text is null || Html is null))
167 {
168 MarkdownDocument Doc = await MarkdownDocument.CreateAsync(Markdown);
169
170 Text ??= await Doc.GeneratePlainText();
171 Html ??= HtmlDocument.GetBody(await Doc.GenerateHTML());
172 }
173
174
175 if (Subject is null && Text is null && Html is null)
176 return true;
177
178 if (Mail is null)
179 {
180 Mail = new OutgoingMail()
181 {
182 Endpoint = this,
183 From = From.BareJid,
184 To = To.BareJid
185 };
186
187 outgoingMails[Key] = Mail;
188 }
189
190 if (!string.IsNullOrEmpty(ReplaceId) &&
191 !(Mail.ById is null) &&
192 Mail.ById.TryGetValue(ReplaceId, out OutgoingMailRec Rec))
193 {
194 Rec.Html = Html;
195 Rec.Text = Text;
196 Rec.Embedded = EmbeddedContent?.ToArray();
197 }
198 else
199 {
200 if (string.IsNullOrEmpty(Mail.Subject))
201 Mail.Subject = Subject;
202 else if (Mail.Subject != Subject && !string.IsNullOrEmpty(Subject))
203 {
204 await Send(Mail);
205 Mail.Subject = Subject;
206 Mail.Records.Clear();
207 Mail.ById?.Clear();
208 }
209
210 if (string.IsNullOrEmpty(Id) && !string.IsNullOrEmpty(ReplaceId))
211 Id = ReplaceId;
212
213 Rec = new OutgoingMailRec()
214 {
215 Id = Id,
216 Html = Html,
217 Text = Text,
218 Embedded = EmbeddedContent?.ToArray()
219 };
220
221 Mail.Records.AddLast(Rec);
222
223 if (!string.IsNullOrEmpty(Id))
224 {
225 Mail.ById ??= new Dictionary<string, OutgoingMailRec>();
226 Mail.ById[Id] = Rec;
227 }
228 }
229
230 if (Immediate)
231 outgoingMails.Remove(Key);
232 }
233 catch (Exception ex)
234 {
235 Log.Exception(ex);
236 }
237 }
238
239 return true;
240 }
241
242 private static async Task OutgoingMails_Removed(object Sender, CacheItemEventArgs<string, OutgoingMail> e)
243 {
244 try
245 {
246 await Send(e.Value);
247 }
248 catch (Exception ex)
249 {
250 Log.Exception(ex);
251 }
252 }
253
254 private static async Task<bool> Send(OutgoingMail Mail)
255 {
256 List<EmbeddedContent> Attachments = null;
257 List<EmbeddedContent> Inline = null;
258 StringBuilder PlainText = null;
259 StringBuilder Html = null;
260 string Id = null;
261
262 foreach (OutgoingMailRec Rec in Mail.Records)
263 {
264 if (Id is null && !string.IsNullOrEmpty(Rec.Id))
265 Id = Rec.Id;
266
267 if (!string.IsNullOrEmpty(Rec.Text))
268 {
269 PlainText ??= new StringBuilder();
270 PlainText.AppendLine(Rec.Text.Trim());
271 }
272
273 if (!string.IsNullOrEmpty(Rec.Html))
274 {
275 Html ??= new StringBuilder();
276 Html.AppendLine(Rec.Html.Trim());
277 }
278
279 if (!(Rec.Embedded is null))
280 {
281 foreach (EmbeddedContent Embedded in Rec.Embedded)
282 {
283 switch (Embedded.Disposition)
284 {
285 case ContentDisposition.Inline:
286 Inline ??= new List<EmbeddedContent>();
287 Inline.Add(Embedded);
288 break;
289
290 case ContentDisposition.Attachment:
291 default:
292 Attachments ??= new List<EmbeddedContent>();
293 Attachments.Add(Embedded);
294 break;
295 }
296 }
297 }
298 }
299
300 List<EmbeddedContent> Alternatives = new List<EmbeddedContent>();
301 string Subject = Mail.Subject;
302 string s;
303
304 if (!(PlainText is null))
305 {
306 s = PlainText.ToString();
307
308 Alternatives.Add(new EmbeddedContent()
309 {
310 ContentType = "text/plain; charset=utf-8",
311 Raw = Encoding.UTF8.GetBytes(s)
312 });
313
314 if (string.IsNullOrEmpty(Subject))
315 Subject = FirstRow(s);
316 }
317
318 if (!(Html is null))
319 {
320 s = Html.ToString();
321
322 EmbeddedContent HtmlContent = new EmbeddedContent()
323 {
324 ContentType = "text/html; charset=utf-8",
325 Raw = Encoding.UTF8.GetBytes(s)
326 };
327
328 if (!(Inline is null) && Inline.Count > 0)
329 {
330 EmbeddedContent[] RelatedContent = new EmbeddedContent[Inline.Count + 1];
331 RelatedContent[0] = HtmlContent;
332 Inline.CopyTo(RelatedContent, 1);
333 RelatedContent Related = new RelatedContent(RelatedContent, HtmlContent.ContentType);
334
335 ContentResponse P = await InternetContent.EncodeAsync(Related, null);
336
337 if (P.HasError)
338 {
340 return false;
341 }
342
343 byte[] Encoded = P.Encoded;
344 string ContentType = P.ContentType;
345
346 HtmlContent = new EmbeddedContent()
347 {
349 Raw = Encoded
350 };
351 }
352
353 Alternatives.Add(HtmlContent);
354
355 if (string.IsNullOrEmpty(Subject))
356 {
357 HtmlDocument Doc = new HtmlDocument("<html><body>" + s + "</body></html>");
358 LinkedList<HtmlNode> ToProcess = new LinkedList<HtmlNode>();
359 string FirstHeader = null;
360 int FirstHeaderLevel = int.MaxValue;
361 string FirstParagraph = null;
362
363 foreach (HtmlNode N in Doc.Body.Children)
364 ToProcess.AddLast(N);
365
366 while (!(ToProcess.First is null))
367 {
368 HtmlNode N = ToProcess.First.Value;
369 ToProcess.RemoveFirst();
370
371 if (N is HtmlElement E)
372 {
373 if (string.Compare(E.FullName, "P", true) == 0)
374 FirstParagraph ??= GetText(E);
375 else if (E.FullName.ToUpper().StartsWith('H') && int.TryParse(E.FullName[1..], out int Level))
376 {
377 if (Level < FirstHeaderLevel)
378 {
379 FirstHeader = GetText(E);
380 FirstHeaderLevel = Level;
381 }
382 }
383
384 if (E.HasChildren)
385 {
386 foreach (HtmlNode N2 in E.Children)
387 ToProcess.AddLast(N2);
388 }
389 }
390 }
391
392 Subject = FirstRow(FirstHeader);
393 if (string.IsNullOrEmpty(Subject))
394 Subject = FirstRow(FirstParagraph);
395 }
396 }
397
398 if (string.IsNullOrEmpty(Subject))
399 Subject = CommonTypes.EncodeRfc822(DateTimeOffset.Now);
400
401 return await Mail.Endpoint.smtpServer.SendMessage(Mail.From, Mail.To, Subject, Id, Alternatives.ToArray(), Attachments?.ToArray());
402 }
403
404 private static string FirstRow(string s)
405 {
406 s = s.Trim();
407 int i = s.IndexOfAny(CommonTypes.CRLF);
408 if (i < 0)
409 return s;
410 else
411 return s[..i].TrimEnd();
412 }
413
414 private static string GetText(HtmlElement E)
415 {
416 StringBuilder Output = new StringBuilder();
417 GetText(E, Output);
418 return Output.ToString();
419 }
420
421 private static void GetText(HtmlElement E, StringBuilder Output)
422 {
423 if (string.Compare(E.FullName, "BR", true) == 0)
424 Output.AppendLine();
425
426 if (E.HasChildren)
427 {
428 foreach (HtmlNode N in E.Children)
429 {
430 if (N is HtmlElement E2)
431 GetText(E2, Output);
432 else if (N is HtmlText Text)
433 Output.Append(Text.InlineText);
434 else if (N is CDATA CDATA)
435 Output.Append(CDATA.Content);
436 }
437 }
438 }
439
441 public override async Task<bool> Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
442 {
443 switch (Type)
444 {
445 case "subscribe":
446 await this.xmppServer.Presence("subscribed", Id, From, To, Language, string.Empty, this);
447
448 StringBuilder Markdown = new StringBuilder();
449
450 Markdown.AppendLine("e-Mail Invitation");
451 Markdown.AppendLine("======================");
452 Markdown.AppendLine();
453
454 Markdown.Append("**");
455 Markdown.Append(MarkdownDocument.Encode(From.BareJid));
456 Markdown.Append("** has added you to its white-list. This means you can send e-mail to **");
457 Markdown.Append(MarkdownDocument.Encode(From.BareJid));
458 Markdown.Append("** from **");
459 Markdown.Append(MarkdownDocument.Encode(To.BareJid));
460 Markdown.AppendLine("**.");
461
462 if (!await this.xmppServer.SendMailMessage(From.BareJid, To.BareJid, "Added to white-list", Markdown.ToString()))
463 return false;
464
465 Log.Informational("Added to white-list.", To.BareJid, From.BareJid);
466 break;
467
468 case "unsubscribe":
469 await this.xmppServer.Presence("unsubscribed", Id, From, To, Language, string.Empty, this);
470
471 Markdown = new StringBuilder();
472
473 Markdown.AppendLine("White-list removal");
474 Markdown.AppendLine("======================");
475 Markdown.AppendLine();
476
477 Markdown.Append("**");
478 Markdown.Append(MarkdownDocument.Encode(From.BareJid));
479 Markdown.Append("** has removed you from its white-list. This means you can no longer send e-mail to **");
480 Markdown.Append(MarkdownDocument.Encode(From.BareJid));
481 Markdown.Append("** from **");
482 Markdown.Append(MarkdownDocument.Encode(To.BareJid));
483 Markdown.AppendLine("**.");
484
485 if (!await this.xmppServer.SendMailMessage(From.BareJid, To.BareJid, "Removed from white-list", Markdown.ToString()))
486 return false;
487
488 Log.Informational("Removed from white-list.", To.BareJid, From.BareJid);
489 break;
490
491 case "subscribed":
492 Markdown = new StringBuilder();
493
494 Markdown.AppendLine("Request approved");
495 Markdown.AppendLine("===================");
496 Markdown.AppendLine();
497
498 Markdown.Append("Your request to be permitted to send e-mail to **");
499 Markdown.Append(MarkdownDocument.Encode(From.BareJid));
500 Markdown.Append("** from **");
501 Markdown.Append(MarkdownDocument.Encode(To.BareJid));
502 Markdown.AppendLine("** has been approved.");
503
504 if (!await this.xmppServer.SendMailMessage(From.BareJid, To.BareJid, "White-listing request approved", Markdown.ToString()))
505 return false;
506
507 Log.Informational("White-listing request approved.", To.BareJid, From.BareJid);
508 break;
509
510 case "unsubscribed":
511 Markdown = new StringBuilder();
512
513 Markdown.AppendLine("Request rejected");
514 Markdown.AppendLine("===================");
515 Markdown.AppendLine();
516
517 Markdown.Append("Your request to be permitted to send e-mail to **");
518 Markdown.Append(MarkdownDocument.Encode(From.BareJid));
519 Markdown.Append("** from **");
520 Markdown.Append(MarkdownDocument.Encode(To.BareJid));
521 Markdown.AppendLine("** has been rejected.");
522
523 if (!await this.xmppServer.SendMailMessage(From.BareJid, To.BareJid, "White-listing request rejected", Markdown.ToString()))
524 return false;
525
526 Log.Informational("White-listing request rejected.", To.BareJid, From.BareJid);
527 break;
528 }
529
530 return true;
531 }
532
534 public override async Task<bool> IQ(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
535 {
536 if (Type == "get" || Type == "set")
537 {
538 StringBuilder sb = new StringBuilder();
539
540 sb.Append("IQ stanzas not supported for mail recipients. From: ");
541 sb.Append(From.Address.Value);
542 sb.Append(", To: ");
543 sb.Append(To.Address.Value);
544
545 return !(await Sender.IqErrorServiceUnavailable(Id, From, To, sb.ToString(), "en") is null);
546 }
547 else
548 return true;
549 }
550
552 public override Task<bool> IQ(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
553 {
554 return this.IQ(Type, Id, To, From, Language, Stanza?.Content, Sender);
555 }
556
558 public override Task<bool> Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
559 {
560 return this.Message(Type, Id, To, From, Language, Stanza?.Content, Sender);
561 }
562
564 public override Task<bool> Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
565 {
566 return this.Presence(Type, Id, To, From, Language, Stanza?.Content, Sender);
567 }
568
570 public override Task<bool> IqError(string Id, XmppAddress To, XmppAddress From, string ErrorXml)
571 {
572 return Task.FromResult(true); // Ignore
573 }
574
576 public override Task<string> IqError(string Id, XmppAddress To, XmppAddress From, Exception ex)
577 {
578 return Task.FromResult(string.Empty); // Ignore
579 }
580
582 public override Task<bool> IqResult(string Id, XmppAddress To, XmppAddress From, string ResultXml)
583 {
584 return Task.FromResult(true); // Ignore
585 }
586
588 public override Task<bool> Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml)
589 {
590 return this.Message(Type, Id, To, From, Language, ContentXml, null);
591 }
592
594 public override Task<bool> MessageError(string Id, XmppAddress To, XmppAddress From, Exception ex)
595 {
596 return Task.FromResult(true); // Ignore
597 }
598
600 public override Task<bool> Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml)
601 {
602 return this.Presence(Type, Id, To, From, Language, ContentXml, null);
603 }
604
606 public override Task<bool> PresenceError(string Id, XmppAddress To, XmppAddress From, string ErrorXml)
607 {
608 return Task.FromResult(true); // Ignore
609 }
610
612 public override Task<bool> PresenceError(string Id, XmppAddress To, XmppAddress From, Exception ex)
613 {
614 return Task.FromResult(true); // Ignore
615 }
616
623 public Task<bool> RelayMessage(SmtpMessage Message, MailAddress Recipient)
624 {
625 StringBuilder Received = new StringBuilder();
626
627 Received.Append("from ");
628 Received.Append(Message.ClientName);
629 Received.Append(" [");
630 Received.Append(Message.RemoteEndPoint);
631 Received.Append("] by ");
632 Received.Append(this.smtpServer.Domain);
633 Received.Append(" with ");
634 Received.Append(typeof(SmtpServer).Namespace);
635 Received.Append(" ");
636 Received.Append(typeof(SmtpServer).Assembly.ImageRuntimeVersion);
637 Received.Append("; ");
638 Received.Append(CommonTypes.EncodeRfc822(DateTimeOffset.Now));
639
640 KeyValuePair<string, string>[] Headers = new KeyValuePair<string, string>[Message.AllHeaders.Length + 1];
641
642 Message.AllHeaders.CopyTo(Headers, 1);
643 Headers[0] = new KeyValuePair<string, string>("Received", Received.ToString());
644
645 return this.smtpServer.SendMessage(Message.FromMail.Address, Recipient.Address, Headers, Message.UntransformedBody, DateTime.Now);
646 }
647
648 }
649}
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static readonly char[] CRLF
Contains the CR LF character sequence.
Definition: CommonTypes.cs:19
static string EncodeRfc822(DateTime Timestamp)
Encodes a date and time, according to RFC 822 §5.
Definition: CommonTypes.cs:669
Contains information about a response to a content request.
byte[] Encoded
Encoded object.
string ContentType
Internet Content-Type of encoded object.
bool HasError
If an error occurred.
Exception Error
Error response.
CDATA content.
Definition: CDATA.cs:11
string Content
CDATA Content
Definition: CDATA.cs:32
HTML encoder/decoder.
Definition: HtmlCodec.cs:15
const string DefaultContentType
Default Content-Type for HTML: text/html
Definition: HtmlCodec.cs:26
static string GetBody(string Html)
Extracts the contents of the BODY element in a HTML string.
Body Body
First BODY element of document, if found, null otherwise.
Base class for all HTML elements.
Definition: HtmlElement.cs:13
bool HasChildren
If the element has children.
Definition: HtmlElement.cs:105
string FullName
Element full name (including prefix).
Definition: HtmlElement.cs:42
IEnumerable< HtmlNode > Children
Child nodes, or null if none.
Definition: HtmlElement.cs:115
Base class for all HTML nodes.
Definition: HtmlNode.cs:11
Static class managing encoding and decoding of internet content.
static Task< ContentResponse > EncodeAsync(object Object, Encoding Encoding, params string[] AcceptedContentTypes)
Encodes an object.
const string ContentType
Markdown content type.
Contains a markdown document. This markdown document class supports original markdown,...
static string Encode(string s)
Encodes all special characters in a string so that it can be included in a markdown document without ...
async Task< string > GeneratePlainText()
Generates Plain Text from the markdown text.
async Task< string > GenerateHTML()
Generates HTML from the markdown text.
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Represents content embedded in other content.
ContentDisposition Disposition
Disposition of embedded object.
string ContentType
Content-Type of embedded object.
Plain text encoder/decoder.
const string DefaultContentType
text/plain
Helps with common XML-related tasks.
Definition: XML.cs:21
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
Definition: XML.cs:1062
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1657
static void Informational(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an informational event.
Definition: Log.cs:344
void Exception(Exception Exception)
Called to inform the viewer of an exception state.
ISniffer[] Sniffers
Registered sniffers.
Represents one message received over SMTP
Definition: SmtpMessage.cs:13
Implements a simple SMTP Server, as defined in:
Definition: SmtpServer.cs:45
Abstract base class for server connections.
CaseInsensitiveString LocalDomain
Local domain name.
CaseInsensitiveString RemoteDomain
Connection to domain.
Manages the connection with an SMTP server.
override async Task< bool > IQ(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
Sends an IQ stanza. If stanza was sent.
SmtpS2SEndpoint(CaseInsensitiveString LocalDomain, CaseInsensitiveString RemoteDomain, SmtpServer SmtpServer, XmppServer XmppServer, params ISniffer[] Sniffers)
Manages the connection with an SMTP server.
override Task< bool > IqError(string Id, XmppAddress To, XmppAddress From, string ErrorXml)
Sends an IQ error stanza. If stanza was sent.
override Task< bool > IQ(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
Sends an IQ stanza. If stanza was sent.
override Task< bool > Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml)
Sends a message stanza. If stanza was sent.
override Task< bool > Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
Sends a presence stanza. If stanza was sent.
override Task< bool > IqResult(string Id, XmppAddress To, XmppAddress From, string ResultXml)
Sends an IQ result stanza. If stanza was sent.
override Task< string > IqError(string Id, XmppAddress To, XmppAddress From, Exception ex)
Sends an IQ error stanza. If stanza was sent.
Task< bool > RelayMessage(SmtpMessage Message, MailAddress Recipient)
Relays a mail message
override Task< bool > PresenceError(string Id, XmppAddress To, XmppAddress From, Exception ex)
Sends a presence error stanza. If stanza was sent.
override Task< bool > Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml)
Sends a presence stanza. If stanza was sent.
override Task< bool > PresenceError(string Id, XmppAddress To, XmppAddress From, string ErrorXml)
Sends a presence error stanza. If stanza was sent.
bool TrustServer
If server should be trusted, regardless if the operating system could validate its certificate or not...
override async Task< bool > Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
Sends a message stanza. If stanza was sent.
override string Type
Type of endpoint
override async Task< bool > Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
Sends a presence stanza. If stanza was sent.
override Task< bool > MessageError(string Id, XmppAddress To, XmppAddress From, Exception ex)
Sends a message error stanza. If stanza was sent.
override Task< bool > Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
Sends a message stanza. If stanza was sent.
Contains information about a stanza.
Definition: Stanza.cs:9
XmlElement StanzaElement
Stanza element.
Definition: Stanza.cs:113
Contains information about one XMPP address.
Definition: XmppAddress.cs:9
override string ToString()
object.ToString()
Definition: XmppAddress.cs:190
CaseInsensitiveString Address
XMPP Address
Definition: XmppAddress.cs:37
CaseInsensitiveString BareJid
Bare JID
Definition: XmppAddress.cs:45
const string ContentNamespace
urn:xmpp:content
Definition: XmppServer.cs:223
const string MailNamespace
urn:xmpp:smtp
Definition: XmppServer.cs:218
Represents a case-insensitive string.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
Implements an in-memory cache.
Definition: Cache.cs:17
void Dispose()
IDisposable.Dispose
Definition: Cache.cs:99
bool Remove(KeyType Key)
Removes an item from the cache.
Definition: Cache.cs:616
bool TryGetValue(KeyType Key, out ValueType Value)
Tries to get a value from the cache.
Definition: Cache.cs:311
Event arguments for cache item removal events.
ValueType Value
Value of item that was removed.
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
Definition: ISniffer.cs:10
Interface for senders of stanzas.
Definition: ISender.cs:10
ContentDisposition
Content disposition
ContentType
DTLS Record content type.
Definition: Enumerations.cs:11