I am working on a project where I have to validate the given SMTP server i.e in a textbox user will provide the detail and then he will click on a test button. I want to check whether the server entered by the user is an Smtp Server or not?
Any Idea??
You might want to improve on this quick code with proper exception handling and maybe also setting the timeouts - it takes about 15 seconds to fail if it can't connect but that might be a limitation of the TCP/IP handshaking.
And sending a QUIT command as Curt suggested would be nice.
private bool ValidSMTP(string hostName)
{
bool valid = false;
try
{
TcpClient smtpTest = new TcpClient();
smtpTest.Connect(hostName, 25);
if (smtpTest.Connected)
{
NetworkStream ns = smtpTest.GetStream();
StreamReader sr = new StreamReader(ns);
if (sr.ReadLine().Contains("220"))
{
valid = true;
}
smtpTest.Close();
}
}
catch
{
}
return valid;
}
Attempt to connect to the SMTP port, and ensure you get a line back from it that starts with "220 " and contains the letters "SMTP". A typical example response would be:
220 prod.monadic.cynic.net ESMTP Postfix (2.5.5)
Then be polite and send "QUIT\r\n" to hang up.
You can do some further testing, if you like, such as testing that the user can likely deliver messages. For this, you'd send a HELO command with your hostname (or any string, really), a MAIL FROM command using the user's e-mail address, and a RCPT TO:<example#example.com>. Most servers at that point will tell you if relaying is not allowed. (I'm assuming you're doing this from the computer from which you will later be sending mail.) So long as you QUIT after that, rather than issuing a DATA command and
the message data, nothing will be sent.
Here's an example session, done from the shell using the "netcat" command, showing that my server exists, but will not relay mail for people from random IP addresses.
$ nc prod.monadic.cynic.net. 25
220 prod.monadic.cynic.net ESMTP Postfix (2.5.5)
HELO cynic.net
250 prod.monadic.cynic.net
MAIL FROM:<cjs#cynic.net>
250 2.1.0 Ok
RCPT TO:<example#example.com>
554 5.7.1 <example#example.com>: Relay access denied
QUIT
221 2.0.0 Bye
$
Related
I have a fully working peerTopeer (P1, P2) webRTC. To handle peerTopeer failures, I am trying for a simple exchange of bytes via a server in c# between P1 and P2 on a windows machine, as I don't want to develop a turn server by specs. I have also tried to find an open source c# server turn server with turn message but its not working (able to parse request but response seems to be not accepted by latest chrome/MS Edge chromium based)
Simple C# relay bridge server:
With simple udp/tcp listener and exchange of bytes with peers, (P1 to P2 and P2 to P1) and forcing bridge machine IP as candidate I am able to achieve connections and streaming data (bytes) are exchanged.
However unable to see video/hear audio on peers and also after some exchange, the connections are dropped with connectionState failed on the client side.
Q1. It should have worked, what is going wrong?
Q2. Any opensource c# implementation of stun and turn (simple one)?
I appreciate any help in this regard.
Server and Client code samples:
Listen to tcp / udp(not in sample)
public void ListenTCP(int port) {
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();
while (true){
TcpClient tcpClient = listener.AcceptTcpClient();
..........add endpoint to list
var bytes = readfromtcpstream.......;
Task.Run(() => ProcessData(tcpClient.Client.RemoteEndPoint, bytes));
}
}
ProcessData (exchange stream bytes)
private void Process_DATA(IPEndPoint fromEndPoint, byte[] bytes) {
foreach (var endpoint in list) { //distribute to all other peers
if (endpoint == fromEndPoint) continue;
endpoint's TCPClient.Send(bytes);
}
}
On the client side (Javascript / typescript), forcing the candidate as bridge server
SignalType.Candidate...
candidate = new RTCIceCandidate(Switch the SDP(messageJson.candidate,
BridgeServerAddress, "2525", "tcp"));
m_PeerConnection.addIceCandidate(candidate)
Simply modifying the ice candidate you got from P2P is unlikely to work since TCP candidates work a bit differently. And a TURN server is very different from a simple bridge.
The following SDP contains a TCP candidate with tcptype passive which will make the other side establish a connection to it. Feed it into setRemoteDescription, then create an answer and call setLocalDescription with the answer.
v=0
o=- 2576067654554894849 3 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:2698387310 1 tcp 25042943 127.0.0.1 31337 typ host tcptype passive generation 0
a=ice-ufrag:server
a=ice-pwd:Kv6yCw1HiZ1/6uNExYcE28pO
a=fingerprint:sha-256 22:46:36:8D:B1:CD:08:7B:A1:60:86:BF:95:90:06:4B:EA:47:D9:74:24:FF:6D:2F:1C:09:5B:C1:F5:8D:CC:B2
a=setup:actpass
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
The browser should establish a connection to port 31337 on localhost (note that Firefox doesn't allow localhost ICE by default so try this in Chrome first).
From there, you'll have to process ICE, decrypt SRTP etc.
I'm not sure why am I getting this result. I'm running this on a Linux server. (It's my small web site's shared web hosting account.)
The files are grouped as follows:
and the Another Dir has one file inside:
So I'm trying to retrieve the contents of the badname directory inside 1somelongdir1234567 directory that doesn't exist on the server, using this code:
try
{
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(
"ftp://server12.some-domain.com/public_html/1somelongdir1234567/badname");
ftpRequest.EnableSsl = true;
ftpRequest.Credentials = new NetworkCredential("user", "password");
ftpRequest.KeepAlive = true;
ftpRequest.Timeout = -1;
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (FtpWebResponse response1 = (FtpWebResponse)ftpRequest.GetResponse())
{
//*****BEGIN OF EDIT*****
Console.WriteLine(response1.StatusDescription);
Console.WriteLine(response1.StatusCode);
//*****END OF EDIT*****
using (StreamReader streamReader = new StreamReader(response1.GetResponseStream()))
{
List<string> arrList = new List<string>();
for (; ; )
{
string line = streamReader.ReadLine();
//I get to here, where `line` is null????
if (string.IsNullOrEmpty(line))
break;
arrList.Add(line);
//*****BEGIN OF EDIT*****
Console.WriteLine(line);
//*****END OF EDIT*****
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
So as you see, there's no such folder badname but instead of throwing an exception, my ftpRequest.GetResponse() succeeds and then streamReader.ReadLine() returns null like I showed in the code above.
More strangely, if I provide an actual directory as such:
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(
"ftp://server12.some-domain.com/public_html/1somelongdir1234567/Another%20Dir");
the streamReader.ReadLine() still returns null.
Can someone explain why?
Edit: OK, guys, I updated the code above to retrieve the status code. I'm still puzzled though.
First, here's three values of connection URI and the response/output that I'm getting:
Example 1:
//Existing folder
"ftp://server12.some-domain.com/public_html/1somelongdir1234567"
Output:
150 Accepted data connection
OpeningData
drwxr-xr-x 3 username username 4096 Sep 5 05:51 .
drwxr-x--- 118 username 99 4096 Sep 5 05:54 ..
drwxr-xr-x 2 username username 4096 Sep 5 05:52 Another Dir
-rw-r--r-- 1 username username 11 Sep 5 05:51 test123.txt
Example 2:
//Another existing folder
"ftp://server12.some-domain.com/public_html/1somelongdir1234567/Another%20Dir"
Output:
150 Accepted data connection
OpeningData
Example 3:
//Nonexistent folder
"ftp://server12.some-domain.com/public_html/1somelongdir1234567/SomeBogusName"
Output:
150 Accepted data connection
OpeningData
So why is it giving me the same result for example 2 as I'm getting for 3?
As for what ftp server it is, I wasn't able to see it in the network logs nor in FtpWebRequest itself. Here's what I was able to get from Microsoft Network Monitor:
Welcome to Pure-FTPd [privsep] [TLS] ----------..
220-You are user number 4 of 50 allowed...
220-Local time is now 13:14. Server port: 21...
220-This is a private system - No anonymous login..
220-IPv6 connections are also welcome on this server...
220 You will be disconnected after 15 minutes of inactivity...
The URL for the ListDirectory/ListDirectoryDetails method should end with a slash, in general.
Without a slash, results tend to be uncertain.
WebRequest.Create("ftp://example.com/public_html/1somelongdir1234567/Another%20Dir/");
As stuartd noted, you get an FTP status code on the response, As far as I know, because of the way FTP commands work, you will never get an exception when a server fails to execute a command you requested. The server will instead just tell you it failed through the FTP response code.
One thing you have to realize is that FTP has no standards for the text it sends back, because it was never designed for its responses to be machine-interpreted. If you got some time, look up the code of FileZilla, and check their class for interpreting the file listings (directorylistingparser.cpp). There are dozens of ways to interpret it, and the application will just try them all until one works. Because, unless you know what kind of FTP you're connecting to, that's the only way to do it.
So if that specific server decides to send an empty string back if you request a nonexistent directory, that's just how their FTP implementation does it, and it's the client's problem to figure out what that means.
If you can't figure out it's a failure from the FTP response code, you can just test if it returns something different for an existing but empty folder. If so, you can easily distinguish between that and this empty response, and treat the empty response as "not found" error in your program.
I want to connect to a cisco switch via telnet in c#.I want to send commands in cmd with c# and when it asks for password I want to enter it with my program. But my problem is that I can’t send password when it is connected to telnet.And when I used StreamWriter it throws an exception.
Here is my code:
class Program
{
static void Main(string[] args)
{
string data = "";
StreamReader reader = new StreamReader(#"C:\Windows\System32");
StreamWriter writer = new StreamWriter(#"C:\Windows\System32");
IPAddress address = IPAddress.Parse("172.16.0.110");
IPEndPoint ipe = new IPEndPoint(address, 23);
Socket telnetSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
telnetSocket.Connect(ipe);
NetworkStream NsStream = new NetworkStream(telnetSocket, true);
if (telnetSocket.Connected)
{
NsStream = new NetworkStream(telnetSocket, true);
reader = new StreamReader(NsStream);
}
while (!reader.EndOfStream)
{
data = reader.ReadLine();
if (data.Contains("Password:"))
{
//I want to enter password in cmd here
}
}
reader.Close();
if (NsStream == null)
NsStream.Close();
}
}
You're going to need to talk Telnet. Telnet rfcs will give you an idead what you're dealing with. https://www.rfc-editor.org/rfc/rfc854
If you want to hand-roll this, a few suggestions that might help. Or else show why it might be a good idea to use a telnet library.
TcpClient will reduce your work a little. At least it will create the NetworkStream for you.
You can probably ignore much of the protocol details, but not the initial option negotiation. You probably want to deal with the raw NetworkStream initially, because telnet sessions start with 'option' negotiation. A quick search for telnet option negotiation turns this up: How to deal with the telnet negotiation
There are two problems using the reader/writer above:
They will be using UTF8 encoding by default, so the telnet option negotiation data (which isn't 7 bit ASCII) will likely get mutated.
Readline() will probably hang anyway, as it will read the telnet options, which are the first thing sent by the server, but then keeping trying to read until the first end of line ... which will never arrive because the server is waiting for a response to the options it sent. i.e. you need to finish the telnet option negotiation.
If you use a lib like SSH.NET you get all these problems solved for you and no need to reinvent the wheel again!
I wrote an app to automatically connect to our different Firewalls. All of them work with the same frontend. We telnet to the IP and they give the message LOGIN or LOGOUT and ask for a username or password.
I used this code:
public static void ConnectToFirewall(string strUsername, string strPassword, string strFirewallIp)
{
IPAddress[] ipaIpAddressCollection = Dns.GetHostAddresses(strFirewallIp);
IPEndPoint ipeIpEndPoint = new IPEndPoint(ipaIpAddressCollection[0], intPort);
Socket sckSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sckSocket.Connect(ipeIpEndPoint);
string strData = strUsername + "\r\n"+ strPassword + "\r\n";
byte[] bytData = new byte[1024];
bytData = Encoding.ASCII.GetBytes(strData);
sckSocket.Send(bytData);
byte[] bytDataReceived = new byte[1024];
int intData = sckSocket.Receive(bytDataReceived);
sckSocket.Close();
}
If I am not logged in, when I telnet to it, I receive the message: LOGIN, username: / Password:.
If I am logged on, I receive LOGOUT, username: / Password.
This works perfectly well with the above method for half of my firewalls, it does not seem to work (I keep getting login as if I had not tried to pass credentials).
I also tried it with
TcpClient tcpConnection = new TcpClient(myip,myport);
but this gives the same result. It works for certain firewall ip's. fails for others. They are all in the same domain.
Does anyone have idea how I could get past this or what steps I could undertake to troubleshoot this or what may be the cause of some server not accepting this method, allthough it does accept if I telnet to it?
Any help or suggestions are appreciated.
Many thanks in advance.
When you call sckSocket.Send(bytData), how does the socket know to send only the portion of the bytData that has been initialized with the username and password? I have a feeling that Send() will send the entire 1024 bytes along, most of which will be 0x00 bytes. I would not expect a router to handle this gracefully.
I've seen systems that accepted the password only after the prompt for the password has been generated and sent. Try sending the username and password with two separate requests. If your environment makes it feasible to set the TCP_NODELAY socket option to disable Nagle's algorithm, it might help to get the username string sent along more quickly. (I wouldn't bother with this unless you also split apart sending the username from the password.)
Does anyone know a way to execute a bulk dump of every email of a gmail account and write the emails to a file?
I'm looking to write a program that would let users back up there gmail (probably via imap) and back it up to either individual files or as a pst (I know pst will probably be much harder)
some time ago I wrote a blog post about exactly same topic. See HOWTO: Download emails from a GMail account in C# for details.
Code uses our Rebex Mail component:
using Rebex.Mail;
using Rebex.Net;
...
// create the POP3 client
Pop3 client = new Pop3();
try
{
// Connect securely using explicit SSL.
// Use the third argument to specify additional SSL parameters.
Console.WriteLine("Connecting to the POP3 server...");
client.Connect("pop.gmail.com", 995, null, Pop3Security.Implicit);
// login and password
client.Login(email, password);
// get the number of messages
Console.WriteLine("{0} messages found.", client.GetMessageCount());
// -----------------
// list messages
// -----------------
// list all messages
ListPop3MessagesFast(client); // unique IDs and size only
//ListPop3MessagesFullHeaders(client); // full headers
}
finally
{
// leave the server alone
client.Disconnect();
}
public static void ListPop3MessagesFast(Pop3 client)
{
Console.WriteLine("Fetching message list...");
// let's download only what we can get fast
Pop3MessageCollection messages =
client.GetMessageList(Pop3ListFields.Fast);
// display basic info about each message
Console.WriteLine("UID | Sequence number | Length");
foreach (Pop3MessageInfo messageInfo in messages)
{
// display header info
Console.WriteLine
(
"{0} | {1} | {2} ",
messageInfo.UniqueId,
messageInfo.SequenceNumber,
messageInfo.Length
);
// or download the whole message
MailMessage mailMessage = client.GetMailMessage(messageInfo.SequenceNumber);
}
}
Gmail provides POP access. So just use any library that allows you to communicate using POP and you're golden.
Edit: I just noticed that you mentioned IMAP; I recommend you use POP instead for bulk dumps. IMAP is too chatty for what you want to do.
If you must use IMAP, here's a library for you.
You can use fetchmail from a Unix environment to create an mbox file.
http://lifehacker.com/software/gmail/geek-to-live--back-up-gmail-with-fetchmail-235207.php
There is an open-source Python program compiled to Windows (using py2exe) at
https://github.com/jay0lee/got-your-back/wiki
But Mac users would need to compile it (which I haven't completely figured out due to a py2exe error).
Either way, you also need a way to execute the program automatically in a schedule.