I am trying to parse out IP addresses from Outlook email headers. I've started writing some stuff in C# (because that is the example I was leveraging) and have come up with something close.
I can split the headers with the string lines[] = Regex.Split(headers, #"\r\n"); command okay, but when I try to iterate through the lines[] array, my regex for IP address fails and does not store the value in a second array:
Code:
private void button1_Click(object sender, EventArgs e)
{
// use a string constant to define the mapi property
string PidTagTransportMessageHeaders = #"http://schemas.microsoft.com/mapi/proptag/0x007D001E";
string mypattern = #"(#{1,3}\.)(#{1,3}\.)([0-9]{1,3}\.)([0-9]{1,3})";
// string[] ip = Regex.Split(lines[i], (#"(\(|\[)(#{1,3}\.)(#{1,3}\.)([0-9]{1,3}\.)([0-9]{1,3})(\)|\])"));
// get a handle on the current message
Outlook.MailItem message = (Outlook.MailItem)this.OutlookItem;
// use the property accessor to retreive the header
string headers = string.Empty;
try
{
headers = (string)message.PropertyAccessor.GetProperty(PidTagTransportMessageHeaders);
}
catch {
}
// if getting the internet headers is successful, put into textbox
string[] lines = Regex.Split(headers, "\r\n");
Regex regexObj = new Regex(mypattern);
for (int i = 0; i < lines.Length; i++)
{
MatchCollection matches = regexObj.Matches(lines[i]);
}
//eventually write the found IP array into textBox1.Text
textBox1.Text = headers;
}
}
}
Any help or suggestions?
Change your #'s to \d's:
string mypattern = #"(\d{1,3}\.)(\d{1,3}\.)(\d{1,3}\.)(\d{1,3})";
Note that a more accurate IPv4 address capture regular expression would be something like:
\b(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b
...or at least add word boundaries...
\b(\d{1,3}\.)(\d{1,3}\.)(\d{1,3}\.)(\d{1,3})\b
For a simple IPv6 (standard) I like:
(?<![:.\w])(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}(?![:.\w])
IPAddress.Parse Method do not reinvent the wheel.
If you're trying to match off IPv4, then try this beast, should be fairly close to what an actual IPv4 can be, the enclosing \b mean beginning and end of a word, so you should be able to remove those and tweak to your heart's content to get the ip based on your header format
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
Related
I'm working on a project, where you have to retrieve data from a server and display it in the UI. It's a newsgroups server, that contains about 250 groups in total.
The output from the server SHOULD as far as I understand, be stored in a NetworkStream object and is read from a StreamReader which saves each line into a string.
This works, but unfortunately it seems like it doesn't finish reading everything before finishing the method call.
Next time I call another command and read it from the StreamReader it then returns the rest of the output from the previous command.
I've been struggling with this for hours now, and can't see how to fix this.
This is my code:
public ObservableCollection<Newsgroup> GetNewsGroups()
{
ObservableCollection<Newsgroup> newsgroups = new ObservableCollection<Newsgroup>();
if(connectionStatus.Equals(ConnectionStatus.CONNECTED) && loginStatus.Equals(LoginStatus.LOGGED_IN))
{
byte[] sendMessage = Encoding.UTF8.GetBytes("LIST\n");
// Write to the server
ns.Write(sendMessage, 0, sendMessage.Length);
Console.WriteLine("Sent {0} bytes to server...", sendMessage.Length);
ns.Flush();
// b) Read from the server
reader = new StreamReader(ns, Encoding.UTF8);
// We want to ignore the first line, as it just contains information about the data
string test = reader.ReadLine();
Console.WriteLine(test);
string recieveMessage = "";
if (ns.CanRead)
{
while (reader.Peek() >= 0)
{
recieveMessage = reader.ReadLine();
Console.WriteLine("Got this message {0} back from the server", recieveMessage);
// This part will simply remove the annoying numbers after the newsgroup name
int firstSpaceIndex = recieveMessage.IndexOf(" ");
string refactoredGroupName = recieveMessage.Substring(0, firstSpaceIndex);
newsgroups.Add(new Newsgroup { GroupName = refactoredGroupName });
}
}
}
return newsgroups;
}
I'd be interested to see what information about the data you are throwing away on the first line (what's in "test" variable). If it tells you how many bytes are coming your way, you should use that information to retrieve the correct amount of data instead of Peek.
If the last line contains a single period, change your while loop to look like this instead:
recieveMessage = reader.ReadLine();
while (recieveMessage != ".")
{
Console.WriteLine("Got this message {0} back from the server", recieveMessage); // This part will simply remove the annoying numbers after the newsgroup name int
firstSpaceIndex = recieveMessage.IndexOf(" ");
string refactoredGroupName = recieveMessage.Substring(0, firstSpaceIndex);
newsgroups.Add(new Newsgroup { GroupName = refactoredGroupName });
recieveMessage = reader.ReadLine();
}
I have a xml with many Ip addresses. Like this:
<settings>
<ipaddresses>
<ipaddress>1288</ipaddress>
<ipaddress>1999</ipaddress>
<ipaddress>555</ipaddress>
<ipaddress>88888</ipaddress>
</ipaddresses>
</settings>
And Now I want to check if one of the Ip Addresses match the Ip address of a pc. So that that user is allowed to see the product.
If the one of the Ipaddresses in the XML not match the Ipaddress of the pc, then a error message has to return. I try it like this:
XDocument doc = XDocument.Parse(product.AuthenticationSettings);
var IpAddress = doc.Descendants("ipaddress");
foreach (var IpAddresses in IpAddress)
{
bool IppAddressMatch = false;
if (GetClientIp() == IpAddresses.Value)
{
IppAddressMatch = true;
}
if (GetClientIp() != IpAddresses.Value)
{
// log message
return Content("<h1>403 Forbidden</h1>", "text/html");
}
}
But I get this error:
Error 6 Warning as Error: The variable 'IppAddressMatch' is assigned
but its value is never used
The code should probably be something like:
XDocument doc = XDocument.Parse(product.AuthenticationSettings);
var IpAddress = doc.Descendants("ipaddress");
bool IppAddressMatch = false;
foreach (var IpAddresses in IpAddress)
{
if (GetClientIp() == IpAddresses.Value)
{
IppAddressMatch = true;
break;
}
}
if (!IppAddressMatch)
{
// log message
return Content("<h1>403 Forbidden</h1>", "text/html");
}
The point is: if the address of the PC is contained in the XML, then everything is OK, but if the address of the PC isn't contained in the XML, then error. Clearly when you find one matching address, you can stop looking for matching addresses (the break)
You have two option to solve this:
Remove the IppAddressMatch variable, because you are not using it.
Change the "treat warnings as errors" option. See Warning as error - How to rid these
I'm using System.Net.Mail to send email in my application but I get an exception and I can't figure out what/where the problem is and how to fix it.
The error says I have some invalid char:
An invalid character was found in the mail header: ';'.
I tried google without success.
The string with email address is:
john#mydomain.org; beth#mydomain.org; alfred#mydomain.org; barbie#mydomain.org;
Here is my email sending code:
SmtpClient smtpClient = new SmtpClient("smtp.........");
System.Net.Mail.MailMessage mailMessagePlainText = new System.Net.Mail.MailMessage();
mailMessagePlainText.IsBodyHtml = true;
mailMessagePlainText.From = new MailAddress("vincent#mydomain.org", "admin");
mailMessagePlainText.Subject = "test";
mailMessagePlainText.Body = "test";
mailMessagePlainText.To.Add(new MailAddress(List1.ToString(), ""));
mailMessagePlainText.Bcc.Add(new MailAddress("vincent#mydomain.org", ""));
try
{
smtpClient.Send(mailMessagePlainText);
}
catch (Exception ex)
{
throw (ex);
}
foreach (var address in List1.split(';')) {
mailMessagePlainText.To.Add(new MailAddress(address.Trim(), ""));
}
Because according to your string here above, each address in this loop above would produce following:
"john#mydomain.org"
" beth#mydomain.org"
" alfred#mydomain.org"
" barbie#mydomain.org"
So by adding .Trim() to address would make your code work.
A MailAddressCollection (like your mailMessagePlainText.To) has an Add method that accepts a string containing a list of mail addresses, separated by a comma.
So to use that, you will need to change the ; into a , and possibly remove the extra spaces.
It looks like you're adding the addresses as a single MailAddress, where you need to add them 1 at a time. I don't know what other overloads are available, but the following will probably work.
I split the string by ; and add each address separately.
replace
mailMessagePlainText.To.Add(new MailAddress(List1.ToString(), ""));
with
foreach (var address in List1.split(';')) {
mailMessagePlainText.To.Add(new MailAddress(address , ""));
}
I have one TELNET SERVER here, and this USSR Vessel v1.0 program is the client, it will be connected to the telnet server, the telnet server SPAMS, I mean sends the data very fast to the client .
(Well, originally the telnet server is a microcontroller that reads 5 sensors and the data will be sent back to the client so this should be quite slower than the C# program telnet server I use as a substitute)
The problem is this, I use regex to split the string coming from the server.
The string should be like this: Q0.00W0.10X0.30Y0.44Z99.00, you see, I'm erasing the Q/W/X/Y/Z and then store the values in a string array and then print them out into 5 labels, but I'm getting this error, see the screenshot below. I added a large textbox for debugging purposes. See my code in receiving the string via telnet:
public void OnAddMessage(string sMessage)
{
//Q0.00W0.10X0.30Y0.44Z99.00
string[] lines = Regex.Split(sMessage, "\r\n");
foreach (string line in lines)
{
Console.WriteLine(line);
valuesStr[ctr2] = line;
ctr2++;
}
ctr2 = 0;
m_lbRecievedData.Items.Add(sMessage);
tempVal.Text = valuesStr[4]+ "°C";
frontVal.Text = valuesStr[0];
backVal.Text = valuesStr[1];
leftVal.Text = valuesStr[2];
rightVal.Text = valuesStr[3];
}
Your question needs more clarification of what you want. As it stands, the code does nothing to accomplish what you claim it to be doing, namely "erasing the Q/W/X/Y/Z and then store the values in a string array".
Nevertheless, here's an attempt at addressing the problem phrased in the question:
using System.Text.RegularExpressions;
private Regex regex = new Regex("[QWXYZ]");
private void OnAddMessage(string message)
{
using (StringReader sr = new StringReader(message))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] splitContents = regex.Split(line);
//do something with the parsed contents ...
}
}
}
Try the RegEx implementation from the Micro Framework
http://netmf.codeplex.com/
Here is a web cast explaining it!
http://channel9.msdn.com/coding4fun/blog/Net-Micro-Framework-v42-RTWs
It's arguably better because it allows you to match for an explicit amount of time and then resume where you left off.. something which is not easily possible by default with the Full Fx.
http://www.codeproject.com/Articles/386890/String-Manipulation-in-the-NET-Micro-Framework
I'm using the following code to receive hex data over the serial port, it seems that some of these transmissions are broken up into 2 lines when they are parts of the same transmission. How do I make sure that each transmission is received properly?
public void Receiver(object sender, SerialDataReceivedEventArgs e)
{
string data;
do
{
data = COMPort.ReadExisting();
} while (COMPort.BytesToRead != 0);
RxARR = data.ToCharArray().ToList();
Dispatcher.Invoke(new MethodInvoker(Display)); // Start "Display" on the UI thread
}
You should never assume that data from a serial port is provided to you in one go (the same is true for network communication by the way). You need to make sure that your code accepts a message only if you have received everything.
Everything is hard to define. This can either be all characters until a defined termination sequence (for example \r\n or EOL byte) or until a fixed number of bytes is read. Generally one can say, as every message can be fragmented, reliable communcation is not possible without a defined end of message signal.
What we do is:
Create a StringBuilder
Read everything into that StringBuilder
Search for termination sequence
Remove everything from the StringBuilder up to and including the termination sequence
Process that chunk of data
Repeat from 3 until termination sequence is not found
Keep the remaining characters in StringBuilder, as this is the start of a new message
Pseudo code:
private StringBuilder serialBuffer = new StringBuilder();
private string terminationSequence = "\r\n"; // Anything that can't be part of a message
public void Receiver(object sender, SerialDataReceivedEventArgs e)
{
string data = COMPort.ReadExisting();
serialBuffer.Append(data);
string bufferString = serialBuffer.ToString();
int index = -1;
do
{
index = bufferString.IndexOf(terminationSequence);
if (index > -1)
{
string message = bufferString.Substring(0, index);
bufferString = bufferString.Remove(0, index + terminationSequence.Length);
HandleMessage(message);
}
}
while (index > -1)
serialBuffer = new StringBuilder(bufferString);
}
By the way: Looping within your DataReceived event is not desired, as this event is called by the SerialPort whenever something new is ready to be read. Reading in a loop may interfere with what SerialPort is doing by default. So: Don't read in a loop within that event! The "loop" is the event being fired in sequence by SerialPort.
I Had almost the same situation.
Like Thorsten said the data sometimes does not come at once..
Maybe because of Hardware or BaundRate..
What really works for me was:
var end = '\r';
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
RxString = Encoding.ASCII.GetString(data);
txtCod.AppendText(RxString);
if (RxString.IndexOf((char)end) > -1)
{
this.Invoke(new EventHandler(Final));
}