I need an application that will intercept all incoming mail messages and modify them according to some specs.
I am an absolute rookie at this, please detail :)
Try this sample code
Dim _tcpClient As New TcpClient
Dim _networkStream As NetworkStream
Dim _Msg As String
With _tcpClient
.Connect(Me.txtServerIp.Text, Integer.Parse(Me.txtPortNum.Text))
_networkStream = .GetStream
Dim sw As New StreamWriter(_networkStream)
Dim sr As New StreamReader(_networkStream)
If Not CheckError(sr.ReadLine()) Then
sw.WriteLine(String.Format("USER {0}", Me.txtUsername.Text))
sw.Flush()
End If
If Not CheckError(sr.ReadLine()) Then
sw.WriteLine(String.Format("PASS {0}", Me.txtPassword.Text))
sw.Flush()
End If
If Not CheckError(sr.ReadLine()) Then
sw.WriteLine("STAT ")
sw.Flush()
End If
_Msg = sr.ReadLine
Dim MsgCount As String = _Msg.Split(New String() {" "}, _
StringSplitOptions.RemoveEmptyEntries)(1)
If Integer.Parse(Me.lblMsgCount.Text) < Integer.Parse(MsgCount) Then
Me.lblMsgCount.Text = MsgCount
End If
sw.WriteLine("Quit ")
sw.Flush()
sw.Close()
sr.Close()
_networkStream.Close()
_tcpClient.Close()
End With
All incoming messages will be coming on over SMTP.
So, you need to do 1 of 2 things:
If your current server supports it, hook into it's SMTP events, and modify the message before it is passed on to the local intended user.
or
You will need a SMTP proxy service, that sits in front of your real SMTP server.
Inside of the SMTP proxy, modify the message, and pass it on to your real SMTP server.
Related
I'm working on a UWP application which should communicate via TCP/UDP to a remote device. My issue is that the UWP app successfully sends UDP messages to the remote device, but does not receive the replies.
Here follows the code extracted from the app (simplified):
async Task TestUdpIP()
{
// Writer to the DatagramSocket
DataWriter writer;
using (var udpClient = new DatagramSocket())
{
try
{
// UDP Socket binding
udpClient.MessageReceived += UdpClient_MessageReceived;
var controllerName = new Windows.Networking.HostName(controllerIpAddress.ToString());
await udpClient.BindEndpointAsync(controllerName, controllerIpPort.ToString());
var remoteHostName = new Windows.Networking.HostName(hostIpAddres.ToString());
await udpClient.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Create a message to send
string message = "Some message";
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpClient.OutputStream);
writer.WriteString(message);
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(5000);
}
catch
{
}
}
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
However the UdpClient_MessageReceived handler does not fire. I'm sure that UDP messages are correctly sent from the UWP app and that the remote device replies back as shown in the following screenshot from Wireshark (the test has been taken on the same PC where the UWP app is running)
.
(IP Address, Port) details are shown in the following list to better explain the picture above
UWP application: (192.168.1.108, 19000) to send and receive.
Remote device: (192.168.1.152, 15999) to receive and (192.168.1.152, 54697) to send
Note: this is a similar question, where the answer says that for whatever reason the DatagramSocket should fire some messages before being able to receive. In my example a message is sent out however the message received handler does not fire anyway.
Note: The UWP app has been granted the internet (client) and the internet (client and server) capabilities
Note: I've tried also this (more readable) approach to bind the inbound/outbound datagram socket on the UWP app obtaining the same results:
// UDP Socket binding
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
EndpointPair endpointpar = new EndpointPair(controllerName,
controllerIpPort.ToString(),
remoteHostName,
remoteHostPort.ToString());
udpClient.MessageReceived += UdpClient_MessageReceived;
await udpClient.ConnectAsync(endpointpar);
Where is the issue? Many thanks!
Please try to also add the Private Networks (Client & Server) capability in your app's manifest.
On other hand, you can try the Official DatagramSocket sample to see whether the both devices can communicate with each other.
After some experimenting, I came out with the idea of using two different DatagramSocket instances: one to send out UDP messages, and one to listen for incoming messages. With this code, I've been able to send UDP messages to the remote device (as before) and also I've been able to receive UDP messages from the remote device.
async Task TestUdpIP_DifferentPorts()
{
// Writer to the DatagramSocket
DataWriter writer;
// Inbound and outbound DatagramSocket
DatagramSocket udpListener = new DatagramSocket();
DatagramSocket udpSender = new DatagramSocket();
try
{
// String containing the serializaed message
string serializedMessage = "Some message";
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
// Bind listener
udpListener.MessageReceived += UdpClient_MessageReceived;
await udpListener.BindEndpointAsync(controllerName, controllerIpPort.ToString());
// Connect sender
await udpSender.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpSender.OutputStream);
writer.WriteString(JsonConvert.SerializeObject(message));
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(1000);
}
catch (Exception ex)
{
// Some exception handling
}
udpSender.Dispose();
udpListener.Dispose();
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
With this approach only the IP port (or service name) of the inbound listener needs to be specified. The framework will choose the next available outbound IP port.
Note: If I understand well the DatagramSocket.ConnectAsync(EndpointPair) documentation, the same DatagramSocket instance can be used to send and listen for incoming message, so I could not figure out the need for two different instances. From the documentation:
This ConnectAsync(EndPointPair) method on a DatagramSocket is used to define the local and remote endpoint where datagrams will be sent when using the OutputStream property. This method also restricts remote IP addresses of packets that will be accepted to the remote hostname in the endpointPair parameter. Only incoming packets that match the remote endpoint in the endpointPair parameter will trigger the MessageReceived event on the DatagramSocket.
I want to use the MailKit Pop3Client to retrieve messages from a POP3 mailbox, and then delete these messages after processing. The retrieval code is something like:
Public Function GetMessages(Optional logPath As String = Nothing) As List(Of MimeMessage)
Dim client As Pop3Client
Dim messages = New List(Of MimeMessage)()
Using client
ConnectPop3(client)
Dim count = client.GetMessageCount()
For i As Integer = 0 To count - 1
Dim msg = client.GetMessage(i)
messages.Add(msg)
Next
End Using
Return messages
End Function
My problem here is in order to delete a message in another message, I need an index, but that is long gone once I exit GetMessages. All I have is the info available on a MimeMessage object, but that has no index property, only MessageId, but in my Delete method, I would have to read all mails again, in order to look up an index value.
Now Pop3Client has a GetMessageUid(int index) method, which returns a mysterious string (looks like int) value with no apparent relation at all to the Mime MessageID, but it seems this is all I have. Then I have to store the MailKit Uid with each message, making my retrieval code something like this, using a dictionary to store uid-message pairs:
Public Function GetMessages(Optional delete As Boolean = False, Optional logPath As String = Nothing) As List(Of MimeMessage)
Dim client As Pop3Client
Dim messages = New Dictionary(Of String, MimeMessage)
Using client
ConnectPop3(client)
Dim count = client.GetMessageCount()
For i As Integer = 0 To count - 1
Dim msg = client.GetMessage(i)
Dim u = client.GetMessageUid(i)
messages.Add(u, msg)
Next
client.Disconnect(True)
End Using
Return messages
End Function
I am really hoping I'm missing something here and what should be a really simple process is indeed simple, but I can't find anything else on my own.
The message UID is the only way to track a message between connections.
The index for a message can change as other messages are deleted.
Your options are:
Delete messages as you're downloading them.
Save the UID so you can come back and delete specific messages later.
It may make more sense if you skim through the POP3 RFC.
The following code listens for an incoming sms, takes all the spaces out of the sms then emails the edited sms. Everything works fine, except that the app fails to send an email. Can anyone see what I am doing wrong and help me?
new Thread() {
public void run() {
try {
DatagramConnection _dc =
(DatagramConnection)Connector.open("sms://");
for(;;) { //'For-Loop' used to listen continously for incoming sms's
Datagram d = _dc.newDatagram(_dc.getMaximumLength());
_dc.receive(d); //The sms is received
byte[] bytes = d.getData();
String address = d.getAddress(); //The address of the sms is put on a string.
String msg = new String(bytes); //The body of the sms is put on a string.
String msg2 = (replaceAll(msg, " ","")) ; //
Store store = Session.getDefaultInstance().getStore();
Folder[] folders = store.list(Folder.SENT);
Folder sentfolder = folders[0]; //Retrieve the sent folder
Message in = new Message(sentfolder);
Address recipients[] = new Address[1];
recipients[0]= new Address("me#yahoo.com", "user");
in.addRecipients(Message.RecipientType.TO, recipients);
in.setSubject("Incoming SMS"); //The subject of the message is added
in.setContent("You have just received an SMS from: " + address + "/n" + "Message: " + msg2); //Here the body of the message is formed
in.setPriority(Message.Priority.HIGH); //The priority of the message is set.
Transport.send(in); //The message is sent
in.setFlag(Message.Flag.OPENED, true);
Folder folder = in.getFolder(); //The message is deleted from the sent folder
folder.deleteMessage(in);
}
}catch (Exception me) { //All Exceptions are caught
}
}
};
public static String replaceAll(String front, String pattern, String back) {
if (front == null)
return "";
StringBuffer sb = new StringBuffer(); //A StringBufffer is created
int idx = -1;
int patIdx = 0;
while ((idx = front.indexOf(pattern, patIdx)) != -1) {
sb.append(front.substring(patIdx, idx));
sb.append(back);
patIdx = idx + pattern.length();
}
sb.append(front.substring(patIdx));
return sb.toString();
}
Thanks
This isn't really an answer to the problem, just an elaboration on my comment above, that might help.
Make sure do something in your exception catch block, so that problems in the code don't go unnoticed. It's possible that your code is not encountering any exceptions, but in order for us to help, we need to try to eliminate potential problems, and since you say the code isn't working, but you have an empty exception handler, that's an easy area to fix first.
the simplest handler is just:
try {
// try sending sms here
} catch (Exception e) {
e.printStackTrace();
}
If you can run this in the debugger (which I highly suggest), then you can now put a breakpoint on the e.printStackTrace() line, and see if it ever gets hit. If it does, inspect the value of e and tell us what it is.
Normally, in my programs, I don't actually use e.printStackTrace() in catch handlers, but I have a logging class that takes strings, and maybe a log level (e.g. info, warning, error, verbose), and writes to a log file. The log file can be attached to emails the users send to tech support, or can be disabled for production if you only want to use the feature while developing.
Anyway, start with a simple printStackTrace() and see if it ever gets hit. Then, report back.
Edit: from the symptoms you describe in the comments after your question, it seems like it's a possibility that
String msg2 = (replaceAll(msg, " ","")) ; //
is throwing an exception, and therefore never letting you get to where you'd send the email. I can't see anything wrong with your implementation of replaceAll() upon initial inspection, but that might be a place to look. Has that implementation been thoroughly unit-tested?
Also, I think you have a "/n" in your code where you probably want a "\n", right?
We're using Amazon SES to send emails, and it says our max send rate is 5 per second.
What happens if we send more than 5 per second? Do they queue or are they rejected?
We have a mailing list that has over 1,000 people on it and they all attempt to send all in one go (and we are approved to use Amazon SES for this purpose).
Here's the code I'm using to send the email:
namespace Amazon
{
public class Emailer
{
/// <summary>
/// Send an email using the Amazon SES service
/// </summary>
public static void SendEmail(String from, String To, String Subject, String HTML = null, String emailReplyTo = null, String returnPath = null)
{
try
{
List<String> to
= To
.Replace(", ", ",")
.Split(',')
.ToList();
var destination = new Destination();
destination.WithToAddresses(to);
var subject = new Content();
subject.WithCharset("UTF-8");
subject.WithData(Subject);
var html = new Content();
html.WithCharset("UTF-8");
html.WithData(HTML);
var body = new Body();
body.WithHtml(html);
var message = new Message();
message.WithBody(body);
message.WithSubject(subject);
var ses = AWSClientFactory.CreateAmazonSimpleEmailServiceClient("xxx", "xxx");
var request = new SendEmailRequest();
request.WithDestination(destination);
request.WithMessage(message);
request.WithSource(from);
if (emailReplyTo != null)
{
List<String> replyto
= emailReplyTo
.Replace(", ", ",")
.Split(',')
.ToList();
request.WithReplyToAddresses(replyto);
}
if (returnPath != null)
request.WithReturnPath(returnPath);
SendEmailResponse response = ses.SendEmail(request);
SendEmailResult result = response.SendEmailResult;
}
catch (Exception e)
{
}
}
}
}
I think that the request are rejected if we are trying to send more messages per second then the allowed limit.
I found this in the SES Blog http://sesblog.amazon.com/post/TxKR75VKOYDS60/How-to-handle-a-quot-Throttling-Maximum-sending-rate-exceeded-quot-error
When you call Amazon SES faster than your maximum allocated send rate, Amazon SES will reject your over the limit requests with a "Throttling – Maximum sending rate exceeded" error.
A "Throttling – Maximum sending rate exceeded" error is retriable. This error is different than other errors returned by Amazon SES, such as sending from an email address that is not verified or sending to an email address that is blacklisted. Those errors indicate that the request will not be accepted in its current form. A request rejected with a "Throttling" error can be retried at a later time and is likely to succeed.
If they would queue the requests this would be a great option but our experience is that they don't. Please let me know if I understand something wrong here.
I've since found out the answer is that they are rejected.
If you attempt to send an email after reaching your daily sending quota (the maximum amount of email you can send in a 24-hour period) or your maximum sending rate (the maximum number of messages you can send per second), Amazon SES drops the message and doesn't attempt to redeliver it.
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/reach-sending-limits.html
I'm getting stuck on this situation and on the way finding the best way for resoling.
Hi i have got a TCP/IP Socket project.
i can send string messages to Server with Client side and i can get responses from server.
But getting one string message and sending only one string (or any other object).I wanna Encode Personel class to Byte array after send to Clients from server side.And Decode it. than get values from my class.
//SERVER SIDE CODE Connect() starts at on form load
private void Connect()
{
// start listen socket
dinleyiciSoket = new TcpListener(System.Net.IPAddress.Any, 10048);
dinleyiciSoket.Start();
Socket istemciSoketi = dinleyiciSoket.AcceptSocket();
NetworkStream agAkisi = new NetworkStream(istemciSoketi);
BinaryReader binaryOkuyucu = new BinaryReader(agAkisi);
BinaryWriter binaryYazici = new BinaryWriter(agAkisi);
string alinanMetin = binaryOkuyucu.ReadString();
MessageBox.Show(alinanMetin, "Yeni Genelge", MessageBoxButtons.OK);
binaryYazici.Write(true);
dinleyiciSoket.Stop();
Connect();
}
////////// CLIENT SIDE //////////////
private string IpAdresi(string host)
{
string address = "";
IPAddress[] addresslist = Dns.GetHostAddresses(host);
foreach (IPAddress theaddress in addresslist)
{
if (theaddress.AddressFamily == AddressFamily.InterNetwork)
{
address = theaddress.ToString();
}
}
return address;
}
bool onay;
private void button1_Click(object sender, EventArgs e)
{
//create socket connection
Socket istemciBaglantisi = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Bağlantıyı gerçekleştir
if (istemciBaglantisi.Connected != true)
{
istemciBaglantisi.Connect(IPAddress.Parse(IpAdresi(txtHost.Text)), 10048);
}
agAkisi = new NetworkStream(istemciBaglantisi);
binaryYazici = new BinaryWriter(agAkisi);
binaryOkuyucu = new BinaryReader(agAkisi);
binaryYazici.Write(txtMesaj.Text);
onay = binaryOkuyucu.ReadBoolean();
MessageBox.Show(onay.ToString());
istemciBaglantisi.Close();
}
Take a look at object serialization. See here for examples. That should get you going in the right direction.
You can use google's protocol buffers. It is a fast and compact mechanism for serializing objects. There are two implementations on .NET: protobuf-net and protobuf.
I'd use object serialization or XmlSerialization, both available in .NET. I would not look at Google's protocol buffers, because that RPC encoding has little advantage over what's already in .NET, but it is obscure, especially in the .NET world, and especially now. I wouldn't bet on it becoming mainstream for .net devs. As a result, you will only make your code harder to maintain by using this RPC encoding.
I don't really see the need for protobufs when the apps that are interconnecting are homogeneous, and are NOT on the scale of Google's datacenters. I also don't see the need even when heterogeneity is the rule, because we already have JSON and XML. They are both readable and serviceable, where protobufs are not.
In any case .NET has what you need for this, built-in.