I'm trying to loop all the messages in specific inbox like using ActiveUp Mail C#:
Mailbox box = imap.AllMailboxes[0];
Fetch fetch = box.Fetch;
int messagesLeft = box.MessageCount; // return 31
int msgIndex = 0;
List<Email> list = new List<Email>();
for (int x = 1; x <= box.MessageCount; x++)
{
try
{
Message msg = fetch.MessageObject(x);
list.Add(new Email()
{
/// .....
});
}
catch { }
}
I'm getting an error for all the messages (except 1)..
Index and length must refer to a location within the string.
all of the messages (Except the 1 that working well) are from the same sender and has the same format (different content)
Imap4Client client = new Imap4Client();
client.Connect("server", 143);
client.Login("***", "***");
foreach (var box in client.AllMailboxes.OfType<Mailbox>())
{
for (int i = 1; i <= box.MessageCount; i++)
{
// a u wish
Header heade = box.Fetch.MessageObject(i);
}
}
Related
I am trying to do a mail app with Windows Forms C#. I only want to see the top 20 rows of my inbox.
Edit:
The code is working fine but only listing me 20 random emails in my inbox
I've tried this:
using (var client = new Pop3Client())
{
client.Connect("pop.gmail.com", 995, true);
client.Authenticate("mail", "passwrd");
for (int i = client.Count - 20; i < client.Count; i++)
{
var message = client.GetMessage(i);
Console.WriteLine("Subject: {0}", message.Subject);
txtBoxMails.AppendText("Subject: " + message.Subject + "\n");
}
client.Disconnect(true);
}
You can use GetMessages. It takes 2 parameters (int startIndex, int count). The index of the first message to get and how many messages.
An example without testing it.
var messages = client.GetMessages(0,20);
foreach (var item in messages)
{
Console.WriteLine(item.Subject);
}
you should use GetMessageCount instead of Count
var messageCount = client.GetMessageCount();
var lastMessageIndex = messageCount-20;
for (int i = messageCount; i > lastMessageIndex; i--)
{
//Do
}
Now I'm making a method, after which the data is successfully sent from the telegram bot to the user. Now I have made this option. However, the problem is that all data is sent separately.
And if we assume we have 20 books in the matrix, we get 21 messages with customer data.
How can I make everything is sent in one message?
private void Form_DataAddAfter(ref SAPbouiCOM.BusinessObjectInfo pVal)
{
SAPbouiCOM.EditText oEdit_Customer = (SAPbouiCOM.EditText)this.GetItem("4").Specific;
SAPbouiCOM.EditText oEdit_Name = (SAPbouiCOM.EditText)this.GetItem("54").Specific;
SAPbouiCOM.EditText oEdit_PostingDate = (SAPbouiCOM.EditText)this.GetItem("10").Specific;
SAPbouiCOM.EditText oEdit_Total = (SAPbouiCOM.EditText)this.GetItem("29").Specific;
SendTextMessage(($"Return of the book!\n\nCustomer: {oEdit_Customer.Value}\nCustomer's name: {oEdit_Name.Value}\nReturn date: {oEdit_PostingDate.Value}\nTotal: {oEdit_Total.Value} "));
for (int j = 1; j < Matrix0.RowCount-1; j++)
{
SAPbouiCOM.EditText cell_Description = (SAPbouiCOM.EditText)Matrix0.Columns.Item("1").Cells.Item(j).Specific;
SAPbouiCOM.EditText cell_Quantity = (SAPbouiCOM.EditText)Matrix0.Columns.Item("U_inUseQuantity").Cells.Item(j).Specific;
SendTextMessage(($"Book: {cell_Description.Value}\nQuantity: {cell_Quantity.Value}"));
}
}
Not tested this code but should work.
Store your "messages" in a string variable add the strings you are currently sending to it. You can then send the string "sendText" after the loop
string sendText = "";
for (int j = 1; j < Matrix0.RowCount-1; j++)
{
SAPbouiCOM.EditText cell_Description = (SAPbouiCOM.EditText)Matrix0.Columns.Item("1").Cells.Item(j).Specific;
SAPbouiCOM.EditText cell_Quantity = (SAPbouiCOM.EditText)Matrix0.Columns.Item("U_inUseQuantity").Cells.Item(j).Specific;
sendText += $"Book: {cell_Description.Value}\nQuantity: {cell_Quantity.Value}\n";
}
SendTextMessage(sendText);
When making a request for HistoricalDataRequest on PX_LAST for a period of a month, I am getting back bulk data. What is wrong with my syntax because I keep getting "Cannot convert SEQUENCE to Element".
//FIELDS
Element fields = security.GetElement(FIELD_DATA);
if (fields.NumElements > 0)
{
int numElements = fields.NumElements;
for (int j = 0; j < numElements; ++j)
{
Element field = fields.GetElement(j);
if (field.Datatype == Schema.Datatype.SEQUENCE || field.IsArray)
{
processBulkField(field, ticker, response);
}
else
{
processRefField(field, ticker, response);
}
}
}
here is the process bulk fields: Error is on the line: Element bulkElement = refBulkfield.GetValueAsElement(i);
private static void processBulkField(Element refBulkfield, string ticker, List<BBGSecurity> response)
{
// Get the total number of Bulk data points
int numofBulkValues = refBulkfield.NumValues;
for (int i = 0; i < numofBulkValues; ++i)
{
Element bulkElement = refBulkfield.GetValueAsElement(i);
// Get the number of sub fields for each bulk data element
int numofBulkElements = bulkElement.NumElements;
// Read each field in Bulk data
for (int j = 0; j < numofBulkElements; ++j)
{
Element field = bulkElement.GetElement(j);
response.Add(new BBGSecurity { Security = ticker, DataDate = DateTime.Parse(d_dataDate), DataSessionID = d_dataSession, Field = field.Name.ToString(), PropertyValue = field.GetValueAsString() });
}
}
}
Thanks in advance!
Please remove field.Datatype == Schema.Datatype.SEQUENCE from the if condition, it should look like:
if (field.IsArray)
{
processBulkField(field, ticker, response);
}
else
{
processRefField(field, ticker, response);
}
Bulk fields are identified by property field.IsArray = True.
Bulk fields contains data set structured as a table with columns and rows, while SEQUENCE field contains data set represented like a C struct.
I'm using a SOAP Web Reference in a C# service for this.
If I call (in my SForceManager class) CreateSForceCase() multiple times within the same connection, I receive the same exact CaseNumber until the connection times out and is reconnected (or if i create a new connection for each).
The problem with this, is that I'm needing to insert upto say 5000 cases, and at 3 seconds per case that will take ~4 hours to insert all 5000 cases. Is there a way to let the API know that I want a brand new case each and every time I create one without logging out?
Here's my Manager code:
public String CreateSForceCase(Case sfCase, out string errMsg)
{
//Verify that we are already authenticated, if not
//call the login function to do so
if (!isConnected()) login();
errMsg = "";
sObject[] objCases = new sObject[1];
for (int j = 0; j < objCases.Length; j++)
objCases[j] = sfCase;
//create the object(s) by sending the array to the web service
SaveResult[] sr = _Binding.create(objCases);
for (int j = 0; j < sr.Length; j++)
{
if (sr[j].success)
{
//save the account ids in a class array
if (_cases == null)
_cases = new string[] { sr[j].id };
else
{
string[] tempcases = null;
tempcases = new string[_cases.Length + 1];
for (int i = 0; i < _cases.Length; i++)
tempcases[i] = _cases[i];
tempcases[_cases.Length] = sr[j].id;
_cases = tempcases;
}
return getCaseNumberFromCaseId(_cases[0]);
}
else
{
//there were errors during the create call, go through the errors
//array and write them to the screen
for (int i = 0; i < sr[j].errors.Length; i++)
{
//get the next error
Error err = sr[j].errors[i];
errMsg = err.message;
}
}
}
return string.Empty;
}
and the call within for getting the case # is:
public String getCaseNumberFromCaseId(string caseId)
{
if (!isConnected()) login();
sObject[] ret = _Binding.retrieve("CaseNumber", "Case", new string[] { caseId });
if (ret != null)
return ((Case)ret[0]).CaseNumber;
else
return string.Empty;
}
so something like:
SForceManager manager = new SForceManager();
string case1 = manager.CreateSForceCase(...);
string case2 = manager.CreateSForceCase(...);
string case3 = manager.CreateSForceCase(...);
then case1 == case2 == case3
but if i do:
SForceManager manager = new SForceManager();
string case1 = manager.CreateSForceCase(...);
SForceManager manager = new SForceManager();
string case2 = manager.CreateSForceCase(...);
SForceManager manager = new SForceManager();
string case3 = manager.CreateSForceCase(...);
then case1 != case2 != case3 like i expect
So I figured out a way to perform this.
The idea is to actually take in a list of "Case objects" and send those all at once, then return a string array of case id's.
I'm not sure what would happen if I try opening too many such that the timeout period may pass in the middle of processing (so it could be improved yet):
public String[] CreateSForceCases(Case[] sfCase, out List<string> errMsg)
{
String[] toRet = new string[sfCase.Length];
errMsg = new List<string>();
//Verify that we are already authenticated, if not
//call the login function to do so
if (!isConnected()) login();
//errMsg = "";
sObject[] objCases = new sObject[sfCase.Length];
for (int j = 0; j < objCases.Length; j++)
objCases[j] = sfCase[j];
//create the object(s) by sending the array to the web service
SaveResult[] sr = _Binding.create(objCases);
for (int j = 0; j < sr.Length; j++)
{
if (sr[j].success)
{
//save the account ids in a class array
if (_cases == null)
_cases = new string[] { sr[j].id };
else
{
string[] tempcases = null;
tempcases = new string[_cases.Length + 1];
for (int i = 0; i < _cases.Length; i++)
tempcases[i] = _cases[i];
tempcases[_cases.Length] = sr[j].id;
_cases = tempcases;
}
toRet[j] = getCaseNumberFromCaseId(_cases[j]);
}
else
{
//there were errors during the create call, go through the errors
//array and write them to the screen
for (int i = 0; i < sr[j].errors.Length; i++)
{
//get the next error
Error err = sr[j].errors[i];
errMsg.Add(err.message);
}
}
}
return toRet;
//return null;
}
There was also a problem in the error handling process in the original, however this one fixes that. I figured I would post my solution in case anyone else has come across this issue...I was not able to find any answer to my question anywhere.
static void barreader_method()
{
barreader.OpenPort(barport, 19200); //opens the port connected to the rfid reader
byte TagType; //tag type
byte[] TagSerial = new byte[4]; //tag serial in reverse order
byte ReturnCode = 0; //return code sent from the rfid reader
string bartagno; //tag no as a string
while (true)
{
bartagno = "";
while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode)) /*wait until a tag is present in the rf field, if present return the tag number.*/
{
}
for (int i = 0; i < 4; i++)
{
bartagno += TagSerial[i].ToString("X2");
}
barprocess(bartagno); //barprocess method
Thread.Sleep(1200); //this is to prevent multiple reads
}
}
If the bartagno variable gets the same value within a minute, i don't want to execute the barprocess method but to continue the infinite loop. Otherwise barprocess method will be executed. How can i achieve this? I don't even know where to start. I tried different datetime, loop combinations with no success.
---------------------------------------------------------progress added below-----------------------------------------------
Multiple cards can be read within a minute, so comparing only with the previous one won't help unfortunately. I tried to use an arraylist instead building on Kelly Ethridge's answer (thanks). But if we get readings once every ten seconds for example, this will be useless. We still have to delete items older than 1 minute.
static void barreader_method()
{
barreader.OpenPort(barport, 19200);
byte TagType;
byte[] TagSerial = new byte[4];
byte ReturnCode = 0;
string bartagno;
ArrayList previoustagnos = new ArrayList();
DateTime lastreaddt = DateTime.MinValue;
while (true)
{
bartagno = "";
while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode))
{
}
for (int i = 0; i < 4; i++)
{
bartagno += TagSerial[i].ToString("X2");
}
if (DateTime.Now - lastreaddt > TimeSpan.FromMinutes(1))
{
previoustagnos.Clear();
barprocess(bartagno);
previoustagnos.Add(bartagno);
lastreaddt = DateTime.Now;
}
else
{
previoustagnos.Sort();
if (previoustagnos.BinarySearch(bartagno) < 0)
{
barprocess(bartagno);
previoustagnos.Add(bartagno);
lastreaddt = DateTime.Now;
}
}
Thread.Sleep(1200);
}
}
You'll need to keep track of the last time the barprocess was called and what the previous bartango was.
static void barreader_method()
{
barreader.OpenPort(barport, 19200); //opens the port connected to the rfid reader
byte TagType; //tag type
byte[] TagSerial = new byte[4]; //tag serial in reverse order
byte ReturnCode = 0; //return code sent from the rfid reader
string bartagno; //tag no as a string
string previousbartango;
var lastTimeCalled = DateTime.MinValue;
while (true)
{
bartagno = "";
while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode)) /*wait until a tag is present in the rf field, if present return the tag number.*/
{
}
for (int i = 0; i < 4; i++)
{
bartagno += TagSerial[i].ToString("X2");
}
var spanSinceLastCalled = DateTime.Now - lastTimeCalled;
if (spanSinceLastCalled > TimeSpan.FromMinutes(1) || bartango != previousbartango)
{
barprocess(bartagno); //barprocess method
previousbartango = bartango;
lastTimeCalled = DateTime.Now;
}
Thread.Sleep(1200); //this is to prevent multiple reads
}
}
This is air-code, but I think you get the idea.
That depends on how many tags you expect to see in a minute.
An ugly way that comes to mind is to create a new variable
List<Tuple<DateTime, String>> recentTags = new List<Tuple<DateTime, String>>()
Every time you see a bartagno, search this list to see if it's already here. If it is, skip over it. If not, add it to the list:
recentTags.Add(Tuple.Create(DateTime.Now, bartagno));
Occasionally (perhaps once 5 - 10 times through your main loop) you'll want to remove old records from this list.
recentTags.RemoveAll(e => e.Item1....
(crud - I don't recall the syntax for "e.Item1 is more than 1 minute in the past")
Isn't it as simple as storing the last processed values and a datetime. If the read is within the time limit then test for sameness before calling the barprocess() method?
...
String lastBarTagNo = "";
DateTime lastTagProcessDateTime = DateTime.MinValue;
...
while(true){
...
// read tag and build new bartagno
if(DateTime.Now - lastTagProcessDateTime <
TimeSpan.FromMinutes(1)) && lastBarTagNo.Equals(bartagno){
barprocess();
}
}
(Sorry about the formatting - doing this on a smart phone)
static void barreader_method()
{
barreader.OpenPort(barport, 19200);
byte TagType;
byte[] TagSerial = new byte[4];
byte ReturnCode = 0;
string bartagno;
List<Tuple<DateTime, String>> previoustags = new List<Tuple<DateTime, String>>();
DateTime lastreaddt = DateTime.MinValue;
while (true)
{
bartagno = "";
while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode))
{
}
for (int i = 0; i < 4; i++)
{
bartagno += TagSerial[i].ToString("X2");
}
if (DateTime.Now - lastreaddt > TimeSpan.FromMinutes(1))
{
previoustags.Clear();
barprocess(bartagno);
previoustags.Add(Tuple.Create(DateTime.Now, bartagno));
lastreaddt = DateTime.Now;
}
else
{
if (!previoustags.Exists(a => a.Item2.Equals(bartagno)))
{
barprocess(bartagno);
previoustags.Add(Tuple.Create(DateTime.Now, bartagno));
lastreaddt = DateTime.Now;
}
}
previoustags.RemoveAll(a => a.Item1.CompareTo(DateTime.Now - TimeSpan.FromMinutes(1)) < 0);
Thread.Sleep(1200);
}
}
Thanks a lot Dan and Kelly. Without your help, i wouldn't be able to solve this.