if ( IdIMAP1->SelectMailBox( "SENT" ) )
{
TIdIMAP4SearchRec sr[1];
sr[0].SearchKey = skAll;
IdIMAP1->UIDSearchMailBox( EXISTINGARRAY(sr) );
int ile = IdIMAP1->MailBox->SearchResult.Length;
}
Error:
First chance exception at $757BF192. Exception class EIdReadLnMaxLineLengthExceeded with message 'Max line length exceeded.'.
It tries to read messages from the SENT folder and the program throws an error. There is no error when receiving from another SENT subfolder.
It seems to me that the problem lies in specifying SearchKey when the value is set to skAll, but no other setting reads the email despite the lack of an error. What does this error mean and how can I fix it?
By the way, I have a question about the SearchKey settings. Is it possible to give a specific date here that would filter emails only from today, for example?
Error:
First chance exception at $757BF192. Exception class EIdReadLnMaxLineLengthExceeded with message 'Max line length exceeded.'.
... What does this error mean and how can I fix it?
It means TIdIMAP4 called the IOHandler.ReadLn() method and received more than 16K worth of data that had no line breaks in it. The default value of the IOHandler.MaxLineLength property is 16384, and the default value of the IOHandler.MaxLineAction is maException.
To workaround the error, you could try increasing the value of the MaxLineLength (say, to MaxInt). However, a proper fix would be to prevent such a large amount of undelimited data to be received in the first place.
The response of UIDSearchMailBox() is a single line containing a list of email sequence numbers delimited by spaces, so you could be getting the EIdReadLnMaxLineLengthExceeded error here if the search is producing a LOT of sequence numbers (say, thousands of them, which makes sense when searching for just skAll on a large mailbox).
You really should not be searching for just skAll by itself to begin with. If you want to access all emails in the mailbox, just iterate the mailbox instead. After SelectMailBox() returns success, TIdIMAP4.MailBox.TotalMsgs will contain the number of emails currently in the mailbox. You can then run a loop retrieving individual emails as needed using sequence numbers in the range of 1..TotalMsgs, inclusive.
Otherwise, filter your search criteria better to produce fewer results.
By the way, I have a question about the SearchKey settings. Is it possible to give a specific date here that would filter emails only from today, for example?
Yes, of course. Look at the TIdIMAP4SearchKey enum, it lists all of the different keys you can search on, for instance:
skOn, //Messages whose internal date is within the specified date.
skSentOn, //Messages whose [RFC-822] Date: header is within the specified date.
skSentSince, //Messages whose [RFC-822] Date: header is within or later than the specified date.
skSince, //Messages whose internal date is within or later than the specified date.
In this case, either of those should work, depending on whether you want to search the email's internal server timestamps or their Date headers, eg:
if ( IdIMAP1->SelectMailBox( "SENT" ) )
{
TIdIMAP4SearchRec sr[1];
sr[0].SearchKey = skSince;
sr[0].Date = Sysutils::Date(); // or Dateutils::Today()
IdIMAP1->UIDSearchMailBox( EXISTINGARRAY(sr) );
int ile = IdIMAP1->MailBox->SearchResult.Length;
}
UPDATE
this example refer to expresion 'later than the specified date' but I can see that it is possible to use 'within'. How to set range of data? Is it possible in SearchKey settings?
There is no 'within' search key in IMAP. If you are referring to RFC 5032: WITHIN Search Extension to the IMAP Protocol (the OLDER and YOUNGER search keys), then TIdIMAP4 does not implement this extension at this time. I have opened a ticket to add it in a future release:
#420: Update TIdIMAP4 to support RFC 5032: "WITHIN Search Extension to the IMAP Protocol"
In the meantime, you can combine multiple search keys and they will be logically AND'ed together, eg:
if ( IdIMAP1->SelectMailBox( "SENT" ) )
{
TDateTime dtNow = Sysutils::Now();
TIdIMAP4SearchRec sr[2];
sr[0].SearchKey = skSince;
sr[0].Date = Dateutils::StartOfTheDay(Dateutils::IncDay(dtNow, -6));
sr[1].SearchKey = skBefore;
sr[1].Date = dtNow;
IdIMAP1->UIDSearchMailBox( EXISTINGARRAY(sr) );
int ile = IdIMAP1->MailBox->SearchResult.Length;
}
I suggest you read RFC 3501 Section 6.4.4 for how the SEARCH command works and what the standard search keys are.
Related
With a printer that doesn't exist, I send to the spooler different files. In my software, I try to get all files existing in the queue of the spooler. For that, I tried the following instruction:
bool t = EnumJobs(hPrinter, 0,1,3, (LPBYTE) &h, sizeof(JOB_INFO_3), &pcbNeeded, &pcReturned)
I get jobId in the field 'JobId' of the structure.
In the structure type 'JOB_INFO_3', the field 'JobId' is well filled but the field 'nextJobId' is not filled. Why?
It's the same problem when I execute the following instruction:
bool t = EnumJobs(hPrinter, 0,3,3, (LPBYTE) &h, sizeof(JOB_INFO_3), &pcbNeeded, &pcReturned)
Moreover, the field 'JobId' is not filled. Why ?
Then, I don't know how to get info(filename, state, number of pages, etc) of a particular job. I tried the following instruction but it didn't work:
GetJobA(hPrinter, h.JobId, 1, (LPBYTE) &job_info_1, sizeof(JOB_INFO_1), & nbBytes)
And my last question is: Is it possible to get all the jobs from the spooler of the printer?
Do you have any solutions?
So, I'm not sure what the rest of your code looks like, but it looks possible that you're not using the API quite correctly. The MSDN documentation suggests that you should call the EnumJobs API twice.
To determine the required buffer size, call EnumJobs with cbBuf set to zero. EnumJobs fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, and the pcbNeeded parameter returns the size, in bytes, of the buffer required to hold the array of structures and their data.
https://msdn.microsoft.com/en-us/library/windows/desktop/dd162625(v=vs.85).aspx
The flow goes like this:
Call EnumJobs for the first time to see how much memory needs to be allocated for your JOB_INFO_n array.
Allocate the memory required for your JOB_INFO_n array.
Call EnumJobs with your JOB_INFO_n array.
Looking at the call to EnumJobs where you attempt to get the first three jobs, the size of your pJob appears to be sizeof(JOB_INFO_3), where it should be three times this size in order to hold all three jobs. What is the return from EnumJobs for that call?
The reason why nextJobId is not filled in is likely a misunderstanding of the field. This field is for print jobs that have been linked together, not to find out which print job is next in the queue.
NextJobId - The print job identifier for the next print job in the linked set of print jobs.
https://msdn.microsoft.com/en-us/library/windows/desktop/dd145021(v=vs.85).aspx
As for the information about the print job, this is going to be difficult. Unfortunately, there is no way I know of to get the name/path of the file printed. There's no concept of this in the spooler APIs. Consider a print job which isn't backed by a file for example. The best you get is the print job name, which is set by the printing application.
For pages, it looks like there is a TotalPages field in the JOB_INFO_1 structure. That may be of some use to you. It looks like you're already trying to get the JOB_INFO_1 structure but having some troubles. If the API is failing, you can use GetLastError() to identify what the issue is. Does the job ID you're passed in exist?
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx
For the last question about getting all print jobs from the queue. It seems that the MSDN documentation suggests the following:
To determine the number of print jobs in the printer queue, call the GetPrinter function with the Level parameter set to 2.
https://msdn.microsoft.com/en-us/library/windows/desktop/dd162625(v=vs.85).aspx
Hope this helps.
I have a LTTNg trace, which i am parsing using babeltrace API. So i was wondering if I could count all events in trace (or stream) without iterating over them. What functions from publilc API I can use to do that ?
The very nature of CTF makes it impossible to count the event records of a given packet in constant time. The packet's context could include an event record count field somehow, but it's not specified, so generic tools would not use it.
Thus the only way to count events is to iterate the event records, unfortunately. The easiest way is to count the number of lines that the text format of the babeltrace(1) tool prints:
babeltrace /path/to/ctf/trace/directory | wc --lines
This works as long as there's one line per printed event record, which is the case unless an event record contains a string field which has a newline (currently not escaped in the text output).
You may also wish to consider discarded event records. They are not printed to the standard output by babeltrace(1), but the tool prints a message including the count to the standard error when they are detected.
There's no way with the current babeltrace(1) tool to only print the event records which belong to the packets of a given data stream. If you need this, what I suggest is that you remove all the data stream files except the one for which you need an event record count, and run the command above again.
Also consider the Babeltrace Python bindings, for example (not tested):
import babeltrace
def count_ctf_event_records(path):
trace_collection = babeltrace.TraceCollection()
trace_collection.add_trace(path, 'ctf')
return sum(1 for event in trace_collection.events)
if __name__ == '__main__':
import sys
print(count_ctf_event_records(sys.argv[1]))
Saved as count.py, you can try this:
python3 count.py /path/to/ctf/trace/directory
Counting the event records of a specific data stream with the Python bindings is left as an exercise for the reader.
Having said this, I don't know if the Python bindings approach is faster than the babeltrace(1) one.
for example, that is data:
1,1470732420000,0
2,1470732421000,0
3,1470732422000,0
4,1470732423000,86
5,1470732424000,87
6,1470732425000,88
7,1470732426000,84
8,1470732427000,0
9,1470732428000,0
10,1470732429000,0
11,1470732430000,89
12,1470732431000,89
13,1470732432000,87
14,1470732433000,89
15,1470732434000,85
16,1470732435000,89
17,1470732436000,89
18,1470732437000,87
19,1470732438000,86
20,1470732439000,88
21,1470732440000,0
22,1470732441000,0
23,1470732442000,0
24,1470732443000,87
25,1470732444000,85
26,1470732445000,86
27,1470732446000,0
28,1470732447000,0
29,1470732448000,0
30,1470732449000,0
column one is id,column two is timestamp,column three is value,1 sec interval between the timestamp.
i want monitoring the value of event,if i found out value>=85(e.g. id=4), i will starting counting,if the next two consecutive value>=85(e.g. id=5/id=6),then i will put the third value of event to OutputStream.(e.g. id=6,value=88,timestamp=1470732425000)
at the same time i clear the counting and wait value lower than 85(e.g. id=7,value=84), then i will monitoring again,when i found out value>=85(e.g. id=11,value=89) i will starting counting,if the next two consecutive value>=85(e.g. id=12/id=13),then i will put the third value of event to OutputStream.(e.g. id=13,value=87,timestamp=1470732432000)...
all this is i wanna do,before i post this ask, i've got an answer in this post,i've tried this code:
from every a1=InputStream[value>=85], a2=InputStream[value>=85]+, a3=InputStream[value<85]
select a2[1].id, a2[1].value
having (not (a2[1] is null))
insert into OutPutStream;
and it works,but i found out it will insert the value into OutputStream after the value<=85,and what i want is if i got three consecutive value>=85 then i insert into the value immediately.(i don't want to wait if the next value>=85 all the times)
in fact, i just wanna record value of third seconds in three consecutive seconds value(>=85) .
i'm using wso2das-3.1.0-SNAPSHOT.
Though DAS (Siddhi) supports sequence/pattern processing, for your requirement you might need to write a custom extension. I have written a sample window processor extension to cater your requirement (source code). Download and place siddhi-extension-condition-window-1.0.jar in <das_home>/repository/components/lib/ directory and restart the server. Refer to the test case to get an idea of the usage of the extension.
I'm stuck on problem were I would like to ask for some help:
I have the task to print some files of different types using ShellExecuteEx with the "print" verb and need to guarantee print order of all files. Therefore I use FindFirstPrinterChangeNotification and FindNextPrinterChangeNotification to monitor the events PRINTER_CHANGE_ADD_JOB and PRINTER_CHANGE_DELETE_JOB using two different threads in the background which I start before calling ShellExecuteEx as I don't know anything about the application which will print the files etc. The only thing I know is that I'm the only one printing and which file I print. My solution seems to work well, my program successfully recognizes the event PRINTER_CHANGE_ADD_JOB for my file, I even verify that this event is issued for my file by checking what is give to me as additional info by specifying JOB_NOTIFY_FIELD_DOCUMENT.
The problem now is with the event PRINTER_CHANGE_DELETE_JOB, where I don't get any addition info about the print job, though my logic is exactly the same for both events: I've written one generic thread function which simply gets executed with the event it is used for. My thread is recognizing the PRINTER_CHANGE_DELETE_JOB event, but on each call to FindNextPrinterChangeNotification whenever this event occured I don't get any addition data in ppPrinterNotifyInfo. This works for the start event, though, I verified using my logs and the debugger. But with PRINTER_CHANGE_DELETE_JOB the only thing I get is NULL.
I already searched the web and there are some similar questions, but most of the time related to VB or simply unanswered. I'm using a C++ project and as my code works for the ADD_JOB-event I don't think I'm doing something completely wrong. But even MSDN doesn't mention this behavior and I would really like to make sure that the DELETE_JOB event is the one for my document, which I can't without any information about the print job. After I get the DELETE_JOB event my code doesn't even recognize other events, which is OK because the print job is done afterwards.
The following is what I think is the relevant notification code:
WORD jobNotifyFields[1] = {JOB_NOTIFY_FIELD_DOCUMENT};
PRINTER_NOTIFY_OPTIONS_TYPE pnot[1] = {JOB_NOTIFY_TYPE, 0, 0, 0, 1, jobNotifyFields};
PRINTER_NOTIFY_OPTIONS pno = {2, 0, 1, pnot};
HANDLE defaultPrinter = PrintWaiter::openDefaultPrinter();
HANDLE changeNotification = FindFirstPrinterChangeNotification( defaultPrinter,
threadArgs->event,
0, &pno);
[...]
DWORD waitResult = WAIT_FAILED;
while ((waitResult = WaitForSingleObject(changeNotification, threadArgs->wfsoTimeout)) == WAIT_OBJECT_0)
{
LOG4CXX_DEBUG(logger, L"Irgendein Druckereignis im Thread zum Warten auf Ereignis " << LogStringConv(threadArgs->event) << L" erkannt.");
[...]
PPRINTER_NOTIFY_INFO notifyInfo = NULL;
DWORD events = 0;
FindNextPrinterChangeNotification(changeNotification, &events, NULL, (LPVOID*) ¬ifyInfo);
if (!(events & threadArgs->event) || !notifyInfo || !notifyInfo->Count)
{
LOG4CXX_DEBUG(logger, L"unpassendes Ereignis " << LogStringConv(events) << L" ignoriert");
FreePrinterNotifyInfo(notifyInfo);
continue;
}
[...]
I would really appreciate if anyone could give some hints on why I don't get any data regarding the print job. Thanks!
https://forums.embarcadero.com/thread.jspa?threadID=86657&stqc=true
Here's what I think is going on:
I observe two events in two different threads for the start and end of each print job. With some debugging and logging I recognized that FindNextPrinterChangeNotification doesn't always return only the two distinct events I've notified for, but some 0-events in general. In those cases FindNextPrinterChangeNotification returns 0 as the events in pdwChange. If I print a simple text file using notepad.exe I only get one event for creation of the print job with value 256 for pdwChange and the data I need in notifyInfo to compare my printed file name against and comparing both succeeds. If I print a pdf file using current Acrobat Reader 11 I get two events, one has pdwChange as 256, but gives something like "local printdatafile" as the name of the print job started, which is obviously not the file I printed. The second event has a pdwChange of 0, but the name of the print job provided in notifyInfo is the file name I used to print. As I use FreePDF for testing pruproses, I think the first printer event is something internal to my special setup.
The notifications for the deletion of a print job create 0 events, too. This time those are sent before FindNextPrinterChangeNotification returns 1024 in pdwChange, and timely very close after the start of the print job. In this case the exactly one generated 0 event contains notifyInfo with a document name which equals the file name I started printing. After the 0 event there's exactly one additional event with pdwChange of 1024, but without any data for notifyInfo.
I think Windows is using some mechanism which provides additional notifications for the same event as 0 events after the initial event has been fired with it's real value the user notified with, e.g. 256 for PRINTER_CHANGE_ADD_JOB. On the other hand it seems that some 0 events are simply fired to provide data for an upcoming event which then gets the real value of e.g. 1024 for PRINTER_CHANGE_DELETE_JOB, but without anymore data because that has already been delivered to the event consumer with a very early 0 event. Something like "Look, there's more for the last events." and "Look, something is going to happen with the data I already provide now." Implementing such an approach my prints now seem to work as expected.
Of course what I wrote doesn't fit to what is documented for FindNextPrinterChangeNotification, but it makes a bit of sense to me. ;-)
You're not checking for overflows or errors.
The documentation for FindNextPrinterChangeNotification says this:
If the PRINTER_NOTIFY_INFO_DISCARDED bit is set in the Flags member of
the PRINTER_NOTIFY_INFO structure, an overflow or error occurred, and
notifications may have been lost. In this case, no additional
notifications will be sent until you make a second
FindNextPrinterChangeNotification call that specifies
PRINTER_NOTIFY_OPTIONS_REFRESH.
You need to check for that flag and do as described above, and you should also be checking the return code from FindNextPrinterChangeNotification.
I am using MAPISendMail() in an MFC application, and am having a problem that webmail clients sometimes receive a winmail.dat attachment, instead of the "real" attachments.
I have researched a lot, and have found that others are experiencing this problem too, but have not found a solution.
I believe that the problem may be in my MapiFileDesc structure, in which I leave the lpFileType member pointing to NULL, in order to have the mail program (In my case Outlook 2010) determine the file type automatically.
lpFiletype is a MapiFileTagExt structure, and the documentation says this:
A value of NULL indicates an unknown file type or a file type determined by the operating system.
So I believe this should work for common types, such as JPEG or GIF and such.
I read that the winmail.dat is caused by Outlook sending the mail encoded with the ms-tnef encoding, which is proprietary to Microsoft. However, when sending the email, Outlook shows "HTML" as highlighted, not RTF.
Has anyone encountered this problem and properly solved it?
Sending via SMTP and such is not an option, because the user should have a copy of the message in their Sent Items folder.
Using the Outlook object model is not an option, because that would require the user has Outlook installed, and not any MAPI compatible client.
I was having similar issue.
I found a KB article that has interesting information in "One-Off Addressing" section, saying that when address is provided in the format [SMTP:SMTP Address] - then e-mail is always sent in rich text format.
For me the fix was not to set "Address" property of MapiRecipDesc object at all. Instead I put the address in Name property. The opening dialog then does not resolve the address at first, but it resolves it right before sending and then it is not sent in RTF!
I even got it working with recipient's name together with address:
MapiRecipDesc.Name = "Firstname Lastname <mail#address.com>";
I, too, was getting all attachments as WinMail.Dat files for the jclMapi.JclEmail, InternalSendOrSave routine, which is called by jclEmail.Send.
What I did was essentially follow jtmnt's answer and changed:
RealAddresses[I] := FAddress; //do not add the Recipients.AddressesType + AddressTypeDelimiter
and I changed:
lpszName := PAnsiChar('"' + AnsiString(RealNames[I])+'" <' +
AnsiString(RealAddresses[I]) + '>');
lpszAddress := '';
This worked so that I no longer was sending WinMail.dat files as attachments, instead the intended PDFs and MP3s were being sent.
What I really want to report is that I was using an OLE routine that was working fine in Windows 7 and stopped working in Windows 8. Thus, I started looking at the MAPI solutions but found this problem with Winmail.dat files being attached. I could not find any mention of this issue with OLE (with Outlook) not working properly in Windows 8.
(Both:
OutlookApp := GetActiveOleObject('Outlook.Application') and
OutlookApp := CreateOleObject('Outlook.Application')
were no longer working in Windows 8, but continued to work fine in Windows 7.)
Thanks for the solution. Thought you might want to know how to apply it to the jclMapi code and this issue with OLE in Win8.
Curious in Outlooks behavior is it does matter what length the domain name of the recipient has! If the e-mail address domain is 12 characters or more (I don’t know what the limit exactly is), then we face the problematic TNEF coding.
So: a#hutsfluts.nl goes wrong. While abacadabraandmore#hf.nl will result in plain text encoding.
I guess this is not by design….
The solution mentioned above:
Put the recepient e-mail address in MapiRecipDesc’s lpszName and let the lpszAddress point to an empty string (NOT null!) solves the problem.
Don’t ask me why, for I have no clue why this would influence the encoding.